1338b8dc3SIngo Weinhold//----------------------------------------------------------------------
2338b8dc3SIngo Weinhold//  This software is part of the Haiku distribution and is covered
3338b8dc3SIngo Weinhold//  by the MIT license.
4338b8dc3SIngo Weinhold//----------------------------------------------------------------------
5338b8dc3SIngo Weinhold/*!
6338b8dc3SIngo Weinhold	\file Node.cpp
7338b8dc3SIngo Weinhold	BNode implementation.
8338b8dc3SIngo Weinhold*/
9338b8dc3SIngo Weinhold
10338b8dc3SIngo Weinhold#include <errno.h>
11338b8dc3SIngo Weinhold#include <fcntl.h>
12338b8dc3SIngo Weinhold#include <fs_attr.h> // for struct attr_info
13338b8dc3SIngo Weinhold#include <new>
14338b8dc3SIngo Weinhold#include <string.h>
15338b8dc3SIngo Weinhold#include <unistd.h>
16338b8dc3SIngo Weinhold
17338b8dc3SIngo Weinhold#include <Directory.h>
18338b8dc3SIngo Weinhold#include <Entry.h>
19338b8dc3SIngo Weinhold#include <Node.h>
20338b8dc3SIngo Weinhold#include <String.h>
21338b8dc3SIngo Weinhold#include <TypeConstants.h>
22338b8dc3SIngo Weinhold
23338b8dc3SIngo Weinhold#include <syscalls.h>
24338b8dc3SIngo Weinhold
25338b8dc3SIngo Weinhold#include "storage_support.h"
26338b8dc3SIngo Weinhold
27338b8dc3SIngo Weinhold//----------------------------------------------------------------------
28338b8dc3SIngo Weinhold// node_ref
29338b8dc3SIngo Weinhold//----------------------------------------------------------------------
30338b8dc3SIngo Weinhold
31338b8dc3SIngo Weinhold// constructor
32338b8dc3SIngo Weinhold/*! \brief Creates an uninitialized node_ref object.
33338b8dc3SIngo Weinhold*/
34338b8dc3SIngo Weinholdnode_ref::node_ref()
35338b8dc3SIngo Weinhold		: device((dev_t)-1),
36338b8dc3SIngo Weinhold		  node((ino_t)-1)
37338b8dc3SIngo Weinhold{
38338b8dc3SIngo Weinhold}
39338b8dc3SIngo Weinhold
40338b8dc3SIngo Weinhold// copy constructor
41338b8dc3SIngo Weinhold/*! \brief Creates a copy of the given node_ref object.
42338b8dc3SIngo Weinhold	\param ref the node_ref to be copied
43338b8dc3SIngo Weinhold*/
44338b8dc3SIngo Weinholdnode_ref::node_ref(const node_ref &ref)
45338b8dc3SIngo Weinhold		: device((dev_t)-1),
46338b8dc3SIngo Weinhold		  node((ino_t)-1)
47338b8dc3SIngo Weinhold{
48338b8dc3SIngo Weinhold	*this = ref;
49338b8dc3SIngo Weinhold}
50338b8dc3SIngo Weinhold
51338b8dc3SIngo Weinhold// ==
52338b8dc3SIngo Weinhold/*! \brief Tests whether this node_ref and the supplied one are equal.
53338b8dc3SIngo Weinhold	\param ref the node_ref to be compared with
54338b8dc3SIngo Weinhold	\return \c true, if the objects are equal, \c false otherwise
55338b8dc3SIngo Weinhold*/
56338b8dc3SIngo Weinholdbool
57338b8dc3SIngo Weinholdnode_ref::operator==(const node_ref &ref) const
58338b8dc3SIngo Weinhold{
59338b8dc3SIngo Weinhold	return (device == ref.device && node == ref.node);
60338b8dc3SIngo Weinhold}
61338b8dc3SIngo Weinhold
62338b8dc3SIngo Weinhold// !=
63338b8dc3SIngo Weinhold/*! \brief Tests whether this node_ref and the supplied one are not equal.
64338b8dc3SIngo Weinhold	\param ref the node_ref to be compared with
65338b8dc3SIngo Weinhold	\return \c false, if the objects are equal, \c true otherwise
66338b8dc3SIngo Weinhold*/
67338b8dc3SIngo Weinholdbool
68338b8dc3SIngo Weinholdnode_ref::operator!=(const node_ref &ref) const
69338b8dc3SIngo Weinhold{
70338b8dc3SIngo Weinhold	return !(*this == ref);
71338b8dc3SIngo Weinhold}
72338b8dc3SIngo Weinhold
73338b8dc3SIngo Weinhold// =
74338b8dc3SIngo Weinhold/*! \brief Makes this node ref a copy of the supplied one.
75338b8dc3SIngo Weinhold	\param ref the node_ref to be copied
76338b8dc3SIngo Weinhold	\return a reference to this object
77338b8dc3SIngo Weinhold*/
78338b8dc3SIngo Weinholdnode_ref&
79338b8dc3SIngo Weinholdnode_ref::operator=(const node_ref &ref)
80338b8dc3SIngo Weinhold{
81338b8dc3SIngo Weinhold	device = ref.device;
82338b8dc3SIngo Weinhold	node = ref.node;
83338b8dc3SIngo Weinhold	return *this;
84338b8dc3SIngo Weinhold}
85338b8dc3SIngo Weinhold
86338b8dc3SIngo Weinhold//----------------------------------------------------------------------
87338b8dc3SIngo Weinhold// BNode
88338b8dc3SIngo Weinhold//----------------------------------------------------------------------
89338b8dc3SIngo Weinhold
90338b8dc3SIngo Weinhold/*!	\brief Creates an uninitialized BNode object
91338b8dc3SIngo Weinhold*/
92338b8dc3SIngo WeinholdBNode::BNode()
93338b8dc3SIngo Weinhold	 : fFd(-1),
94338b8dc3SIngo Weinhold	   fAttrFd(-1),
95338b8dc3SIngo Weinhold	   fCStatus(B_NO_INIT)
96338b8dc3SIngo Weinhold{
97338b8dc3SIngo Weinhold}
98338b8dc3SIngo Weinhold
99338b8dc3SIngo Weinhold/*!	\brief Creates a BNode object and initializes it to the specified
100338b8dc3SIngo Weinhold	entry_ref.
101338b8dc3SIngo Weinhold	\param ref the entry_ref referring to the entry
102338b8dc3SIngo Weinhold*/
103338b8dc3SIngo WeinholdBNode::BNode(const entry_ref *ref)
104338b8dc3SIngo Weinhold	 : fFd(-1),
105338b8dc3SIngo Weinhold	   fAttrFd(-1),
106338b8dc3SIngo Weinhold	   fCStatus(B_NO_INIT)
107338b8dc3SIngo Weinhold{
108338b8dc3SIngo Weinhold	SetTo(ref);
109338b8dc3SIngo Weinhold}
110338b8dc3SIngo Weinhold
111338b8dc3SIngo Weinhold/*!	\brief Creates a BNode object and initializes it to the specified
112338b8dc3SIngo Weinhold	filesystem entry.
113338b8dc3SIngo Weinhold	\param entry the BEntry representing the entry
114338b8dc3SIngo Weinhold*/
115338b8dc3SIngo WeinholdBNode::BNode(const BEntry *entry)
116338b8dc3SIngo Weinhold	 : fFd(-1),
117338b8dc3SIngo Weinhold	   fAttrFd(-1),
118338b8dc3SIngo Weinhold	   fCStatus(B_NO_INIT)
119338b8dc3SIngo Weinhold{
120338b8dc3SIngo Weinhold	SetTo(entry);
121338b8dc3SIngo Weinhold}
122338b8dc3SIngo Weinhold
123338b8dc3SIngo Weinhold/*!	\brief Creates a BNode object and initializes it to the entry referred
124338b8dc3SIngo Weinhold	to by the specified path.
125338b8dc3SIngo Weinhold	\param path the path referring to the entry
126338b8dc3SIngo Weinhold*/
127338b8dc3SIngo WeinholdBNode::BNode(const char *path)
128338b8dc3SIngo Weinhold	 : fFd(-1),
129338b8dc3SIngo Weinhold	   fAttrFd(-1),
130338b8dc3SIngo Weinhold	   fCStatus(B_NO_INIT)
131338b8dc3SIngo Weinhold{
132338b8dc3SIngo Weinhold	SetTo(path);
133338b8dc3SIngo Weinhold}
134338b8dc3SIngo Weinhold
135338b8dc3SIngo Weinhold/*!	\brief Creates a BNode object and initializes it to the entry referred
136338b8dc3SIngo Weinhold	to by the specified path rooted in the specified directory.
137338b8dc3SIngo Weinhold	\param dir the BDirectory, relative to which the entry's path name is
138338b8dc3SIngo Weinhold		   given
139338b8dc3SIngo Weinhold	\param path the entry's path name relative to \a dir
140338b8dc3SIngo Weinhold*/
141338b8dc3SIngo WeinholdBNode::BNode(const BDirectory *dir, const char *path)
142338b8dc3SIngo Weinhold	 : fFd(-1),
143338b8dc3SIngo Weinhold	   fAttrFd(-1),
144338b8dc3SIngo Weinhold	   fCStatus(B_NO_INIT)
145338b8dc3SIngo Weinhold{
146338b8dc3SIngo Weinhold	SetTo(dir, path);
147338b8dc3SIngo Weinhold}
148338b8dc3SIngo Weinhold
149338b8dc3SIngo Weinhold/*! \brief Creates a copy of the given BNode.
150338b8dc3SIngo Weinhold	\param node the BNode to be copied
151338b8dc3SIngo Weinhold*/
152338b8dc3SIngo WeinholdBNode::BNode(const BNode &node)
153338b8dc3SIngo Weinhold	 : fFd(-1),
154338b8dc3SIngo Weinhold	   fAttrFd(-1),
155338b8dc3SIngo Weinhold	   fCStatus(B_NO_INIT)
156338b8dc3SIngo Weinhold{
157338b8dc3SIngo Weinhold	*this = node;
158338b8dc3SIngo Weinhold}
159338b8dc3SIngo Weinhold
160338b8dc3SIngo Weinhold/*!	\brief Frees all resources associated with this BNode.
161338b8dc3SIngo Weinhold*/
162338b8dc3SIngo WeinholdBNode::~BNode()
163338b8dc3SIngo Weinhold{
164338b8dc3SIngo Weinhold	Unset();
165338b8dc3SIngo Weinhold}
166338b8dc3SIngo Weinhold
167338b8dc3SIngo Weinhold/*!	\brief Checks whether the object has been properly initialized or not.
168338b8dc3SIngo Weinhold	\return
169338b8dc3SIngo Weinhold	- \c B_OK, if the object has been properly initialized,
170338b8dc3SIngo Weinhold	- an error code, otherwise.
171338b8dc3SIngo Weinhold*/
172338b8dc3SIngo Weinholdstatus_t
173338b8dc3SIngo WeinholdBNode::InitCheck() const
174338b8dc3SIngo Weinhold{
175338b8dc3SIngo Weinhold	return fCStatus;
176338b8dc3SIngo Weinhold}
177338b8dc3SIngo Weinhold
178338b8dc3SIngo Weinhold/*! \brief Fills in the given stat structure with \code stat() \endcode
179338b8dc3SIngo Weinhold		   information for this object.
180338b8dc3SIngo Weinhold	\param st a pointer to a stat structure to be filled in
181338b8dc3SIngo Weinhold	\return
182338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
183338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a st.
184338b8dc3SIngo Weinhold	- another error code, e.g., if the object wasn't properly initialized
185338b8dc3SIngo Weinhold*/
186338b8dc3SIngo Weinholdstatus_t
187338b8dc3SIngo WeinholdBNode::GetStat(struct stat *st) const
188338b8dc3SIngo Weinhold{
189338b8dc3SIngo Weinhold	return (fCStatus != B_OK)
190338b8dc3SIngo Weinhold		? fCStatus
191338b8dc3SIngo Weinhold		: _kern_read_stat(fFd, NULL, false, st, sizeof(struct stat));
192338b8dc3SIngo Weinhold}
193338b8dc3SIngo Weinhold
194338b8dc3SIngo Weinhold/*! \brief Reinitializes the object to the specified entry_ref.
195338b8dc3SIngo Weinhold	\param ref the entry_ref referring to the entry
196338b8dc3SIngo Weinhold	\return
197338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
198338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a ref.
199338b8dc3SIngo Weinhold	- \c B_ENTRY_NOT_FOUND: The entry could not be found.
200338b8dc3SIngo Weinhold	- \c B_BUSY: The entry is locked.
201338b8dc3SIngo Weinhold*/
202338b8dc3SIngo Weinholdstatus_t
203338b8dc3SIngo WeinholdBNode::SetTo(const entry_ref *ref)
204338b8dc3SIngo Weinhold{
205338b8dc3SIngo Weinhold	return _SetTo(ref, false);
206338b8dc3SIngo Weinhold}
207338b8dc3SIngo Weinhold
208338b8dc3SIngo Weinhold/*!	\brief Reinitializes the object to the specified filesystem entry.
209338b8dc3SIngo Weinhold	\param entry the BEntry representing the entry
210338b8dc3SIngo Weinhold	\return
211338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
212338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a entry.
213338b8dc3SIngo Weinhold	- \c B_ENTRY_NOT_FOUND: The entry could not be found.
214338b8dc3SIngo Weinhold	- \c B_BUSY: The entry is locked.
215338b8dc3SIngo Weinhold*/
216338b8dc3SIngo Weinholdstatus_t
217338b8dc3SIngo WeinholdBNode::SetTo(const BEntry *entry)
218338b8dc3SIngo Weinhold{
219338b8dc3SIngo Weinhold	if (!entry) {
220338b8dc3SIngo Weinhold		Unset();
221338b8dc3SIngo Weinhold		return (fCStatus = B_BAD_VALUE);
222338b8dc3SIngo Weinhold	}
223338b8dc3SIngo Weinhold	return _SetTo(entry->fDirFd, entry->fName, false);
224338b8dc3SIngo Weinhold}
225338b8dc3SIngo Weinhold
226338b8dc3SIngo Weinhold/*!	\brief Reinitializes the object to the entry referred to by the specified
227338b8dc3SIngo Weinhold		   path.
228338b8dc3SIngo Weinhold	\param path the path referring to the entry
229338b8dc3SIngo Weinhold	\return
230338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
231338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a path.
232338b8dc3SIngo Weinhold	- \c B_ENTRY_NOT_FOUND: The entry could not be found.
233338b8dc3SIngo Weinhold	- \c B_BUSY: The entry is locked.
234338b8dc3SIngo Weinhold*/
235338b8dc3SIngo Weinholdstatus_t
236338b8dc3SIngo WeinholdBNode::SetTo(const char *path)
237338b8dc3SIngo Weinhold{
238338b8dc3SIngo Weinhold	return _SetTo(-1, path, false);
239338b8dc3SIngo Weinhold}
240338b8dc3SIngo Weinhold
241338b8dc3SIngo Weinhold/*! \brief Reinitializes the object to the entry referred to by the specified
242338b8dc3SIngo Weinhold	path rooted in the specified directory.
243338b8dc3SIngo Weinhold	\param dir the BDirectory, relative to which the entry's path name is
244338b8dc3SIngo Weinhold		   given
245338b8dc3SIngo Weinhold	\param path the entry's path name relative to \a dir
246338b8dc3SIngo Weinhold	\return
247338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
248338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a dir or \a path.
249338b8dc3SIngo Weinhold	- \c B_ENTRY_NOT_FOUND: The entry could not be found.
250338b8dc3SIngo Weinhold	- \c B_BUSY: The entry is locked.
251338b8dc3SIngo Weinhold*/
252338b8dc3SIngo Weinholdstatus_t
253338b8dc3SIngo WeinholdBNode::SetTo(const BDirectory *dir, const char *path)
254338b8dc3SIngo Weinhold{
255338b8dc3SIngo Weinhold	if (!dir || !path || BPrivate::Storage::is_absolute_path(path)) {
256338b8dc3SIngo Weinhold		Unset();
257338b8dc3SIngo Weinhold		return (fCStatus = B_BAD_VALUE);
258338b8dc3SIngo Weinhold	}
259338b8dc3SIngo Weinhold	return _SetTo(dir->fDirFd, path, false);
260338b8dc3SIngo Weinhold}
261338b8dc3SIngo Weinhold
262338b8dc3SIngo Weinhold/*!	\brief Returns the object to an uninitialized state.
263338b8dc3SIngo Weinhold*/
264338b8dc3SIngo Weinholdvoid
265338b8dc3SIngo WeinholdBNode::Unset()
266338b8dc3SIngo Weinhold{
267338b8dc3SIngo Weinhold	close_fd();
268338b8dc3SIngo Weinhold	fCStatus = B_NO_INIT;
269338b8dc3SIngo Weinhold}
270338b8dc3SIngo Weinhold
271338b8dc3SIngo Weinhold/*!	\brief Attains an exclusive lock on the data referred to by this node, so
272338b8dc3SIngo Weinhold	that it may not be modified by any other objects or methods.
273338b8dc3SIngo Weinhold	\return
274338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
275338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: The object is not initialized.
276338b8dc3SIngo Weinhold	- \c B_BUSY: The node is already locked.
277338b8dc3SIngo Weinhold*/
278338b8dc3SIngo Weinholdstatus_t
279338b8dc3SIngo WeinholdBNode::Lock()
280338b8dc3SIngo Weinhold{
281338b8dc3SIngo Weinhold	if (fCStatus != B_OK)
282338b8dc3SIngo Weinhold		return fCStatus;
283338b8dc3SIngo Weinhold	return _kern_lock_node(fFd);
284338b8dc3SIngo Weinhold}
285338b8dc3SIngo Weinhold
286338b8dc3SIngo Weinhold/*!	\brief Unlocks the node.
287338b8dc3SIngo Weinhold	\return
288338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
289338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: The object is not initialized.
290338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: The node is not locked.
291338b8dc3SIngo Weinhold*/
292338b8dc3SIngo Weinholdstatus_t
293338b8dc3SIngo WeinholdBNode::Unlock()
294338b8dc3SIngo Weinhold{
295338b8dc3SIngo Weinhold	if (fCStatus != B_OK)
296338b8dc3SIngo Weinhold		return fCStatus;
297338b8dc3SIngo Weinhold	return _kern_unlock_node(fFd);
298338b8dc3SIngo Weinhold}
299338b8dc3SIngo Weinhold
300338b8dc3SIngo Weinhold/*!	\brief Immediately performs any pending disk actions on the node.
301338b8dc3SIngo Weinhold	\return
302338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
303338b8dc3SIngo Weinhold	- an error code, if something went wrong.
304338b8dc3SIngo Weinhold*/
305338b8dc3SIngo Weinholdstatus_t
306338b8dc3SIngo WeinholdBNode::Sync()
307338b8dc3SIngo Weinhold{
308338b8dc3SIngo Weinhold	return (fCStatus != B_OK) ? B_FILE_ERROR : _kern_fsync(fFd);
309338b8dc3SIngo Weinhold}
310338b8dc3SIngo Weinhold
311338b8dc3SIngo Weinhold/*!	\brief Writes data from a buffer to an attribute.
312338b8dc3SIngo Weinhold	Write the \a len bytes of data from \a buffer to
313338b8dc3SIngo Weinhold	the attribute specified by \a name after erasing any data
314338b8dc3SIngo Weinhold	that existed previously. The type specified by \a type \em is
315338b8dc3SIngo Weinhold	remembered, and may be queried with GetAttrInfo(). The value of
316338b8dc3SIngo Weinhold	\a offset is currently ignored.
317338b8dc3SIngo Weinhold	\param attr the name of the attribute
318338b8dc3SIngo Weinhold	\param type the type of the attribute
319338b8dc3SIngo Weinhold	\param offset the index at which to write the data (currently ignored)
320338b8dc3SIngo Weinhold	\param buffer the buffer containing the data to be written
321338b8dc3SIngo Weinhold	\param len the number of bytes to be written
322338b8dc3SIngo Weinhold	\return
323338b8dc3SIngo Weinhold	- the number of bytes actually written
324338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a attr or \a buffer
325338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: The object is not initialized or the node it refers to
326338b8dc3SIngo Weinhold	  is read only.
327338b8dc3SIngo Weinhold	- \c B_NOT_ALLOWED: The node resides on a read only volume.
328338b8dc3SIngo Weinhold	- \c B_DEVICE_FULL: Insufficient disk space.
329338b8dc3SIngo Weinhold	- \c B_NO_MEMORY: Insufficient memory to complete the operation.
330338b8dc3SIngo Weinhold*/
331338b8dc3SIngo Weinholdssize_t
332338b8dc3SIngo WeinholdBNode::WriteAttr(const char *attr, type_code type, off_t offset,
333338b8dc3SIngo Weinhold				 const void *buffer, size_t len)
334338b8dc3SIngo Weinhold{
335338b8dc3SIngo Weinhold	if (fCStatus != B_OK)
336338b8dc3SIngo Weinhold		return B_FILE_ERROR;
337338b8dc3SIngo Weinhold	if (!attr || !buffer)
338338b8dc3SIngo Weinhold		return B_BAD_VALUE;
339338b8dc3SIngo Weinhold	ssize_t result = fs_write_attr (fFd, attr, type, offset, buffer, len);
340338b8dc3SIngo Weinhold	return (result < 0 ? errno : result);
341338b8dc3SIngo Weinhold}
342338b8dc3SIngo Weinhold
343338b8dc3SIngo Weinhold/*!	\brief Reads data from an attribute into a buffer.
344338b8dc3SIngo Weinhold	Reads the data of the attribute given by \a name into
345338b8dc3SIngo Weinhold	the buffer specified by \a buffer with length specified
346338b8dc3SIngo Weinhold	by \a len. \a type and \a offset are currently ignored.
347338b8dc3SIngo Weinhold	\param attr the name of the attribute
348338b8dc3SIngo Weinhold	\param type the type of the attribute (currently ignored)
349338b8dc3SIngo Weinhold	\param offset the index from which to read the data (currently ignored)
350338b8dc3SIngo Weinhold	\param buffer the buffer for the data to be read
351338b8dc3SIngo Weinhold	\param len the number of bytes to be read
352338b8dc3SIngo Weinhold	\return
353338b8dc3SIngo Weinhold	- the number of bytes actually read
354338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a attr or \a buffer
355338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: The object is not initialized.
356338b8dc3SIngo Weinhold	- \c B_ENTRY_NOT_FOUND: The node has no attribute \a attr.
357338b8dc3SIngo Weinhold*/
358338b8dc3SIngo Weinholdssize_t
359338b8dc3SIngo WeinholdBNode::ReadAttr(const char *attr, type_code type, off_t offset,
360338b8dc3SIngo Weinhold				void *buffer, size_t len) const
361338b8dc3SIngo Weinhold{
362338b8dc3SIngo Weinhold	if (fCStatus != B_OK)
363338b8dc3SIngo Weinhold		return B_FILE_ERROR;
364338b8dc3SIngo Weinhold	if (!attr || !buffer)
365338b8dc3SIngo Weinhold		return B_BAD_VALUE;
366338b8dc3SIngo Weinhold	ssize_t result = fs_read_attr(fFd, attr, type, offset, buffer, len );
367338b8dc3SIngo Weinhold	return (result == -1 ? errno : result);
368338b8dc3SIngo Weinhold}
369338b8dc3SIngo Weinhold
370338b8dc3SIngo Weinhold/*!	\brief Deletes the attribute given by \a name.
371338b8dc3SIngo Weinhold	\param name the name of the attribute
372338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
373338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a name
374338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: The object is not initialized or the node it refers to
375338b8dc3SIngo Weinhold	  is read only.
376338b8dc3SIngo Weinhold	- \c B_ENTRY_NOT_FOUND: The node has no attribute \a name.
377338b8dc3SIngo Weinhold	- \c B_NOT_ALLOWED: The node resides on a read only volume.
378338b8dc3SIngo Weinhold*/
379338b8dc3SIngo Weinholdstatus_t
380338b8dc3SIngo WeinholdBNode::RemoveAttr(const char *name)
381338b8dc3SIngo Weinhold{
382338b8dc3SIngo Weinhold	return (fCStatus != B_OK) ? B_FILE_ERROR : _kern_remove_attr(fFd, name);
383338b8dc3SIngo Weinhold}
384338b8dc3SIngo Weinhold
385338b8dc3SIngo Weinhold/*!	\brief Moves the attribute given by \a oldname to \a newname.
386338b8dc3SIngo Weinhold	If \a newname already exists, the current data is clobbered.
387338b8dc3SIngo Weinhold	\param oldname the name of the attribute to be renamed
388338b8dc3SIngo Weinhold	\param newname the new name for the attribute
389338b8dc3SIngo Weinhold	\return
390338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
391338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a oldname or \a newname
392338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: The object is not initialized or the node it refers to
393338b8dc3SIngo Weinhold	  is read only.
394338b8dc3SIngo Weinhold	- \c B_ENTRY_NOT_FOUND: The node has no attribute \a oldname.
395338b8dc3SIngo Weinhold	- \c B_NOT_ALLOWED: The node resides on a read only volume.
396338b8dc3SIngo Weinhold*/
397338b8dc3SIngo Weinholdstatus_t
398338b8dc3SIngo WeinholdBNode::RenameAttr(const char *oldname, const char *newname)
399338b8dc3SIngo Weinhold{
400338b8dc3SIngo Weinhold	if (fCStatus != B_OK)
401338b8dc3SIngo Weinhold		return B_FILE_ERROR;
402338b8dc3SIngo Weinhold	return _kern_rename_attr(fFd, oldname, fFd, newname);
403338b8dc3SIngo Weinhold}
404338b8dc3SIngo Weinhold
405338b8dc3SIngo Weinhold
406338b8dc3SIngo Weinhold/*!	\brief Fills in the pre-allocated attr_info struct pointed to by \a info
407338b8dc3SIngo Weinhold	with useful information about the attribute specified by \a name.
408338b8dc3SIngo Weinhold	\param name the name of the attribute
409338b8dc3SIngo Weinhold	\param info the attr_info structure to be filled in
410338b8dc3SIngo Weinhold	\return
411338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
412338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a name
413338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: The object is not initialized.
414338b8dc3SIngo Weinhold	- \c B_ENTRY_NOT_FOUND: The node has no attribute \a name.
415338b8dc3SIngo Weinhold*/
416338b8dc3SIngo Weinholdstatus_t
417338b8dc3SIngo WeinholdBNode::GetAttrInfo(const char *name, struct attr_info *info) const
418338b8dc3SIngo Weinhold{
419338b8dc3SIngo Weinhold	if (fCStatus != B_OK)
420338b8dc3SIngo Weinhold		return B_FILE_ERROR;
421338b8dc3SIngo Weinhold	if (!name || !info)
422338b8dc3SIngo Weinhold		return B_BAD_VALUE;
423338b8dc3SIngo Weinhold	return (fs_stat_attr(fFd, name, info) < 0) ? errno : B_OK ;
424338b8dc3SIngo Weinhold}
425338b8dc3SIngo Weinhold
426338b8dc3SIngo Weinhold/*!	\brief Returns the next attribute in the node's list of attributes.
427338b8dc3SIngo Weinhold	Every BNode maintains a pointer to its list of attributes.
428338b8dc3SIngo Weinhold	GetNextAttrName() retrieves the name of the attribute that the pointer is
429338b8dc3SIngo Weinhold	currently pointing to, and then bumps the pointer to the next attribute.
430338b8dc3SIngo Weinhold	The name is copied into the buffer, which should be at least
431338b8dc3SIngo Weinhold	B_ATTR_NAME_LENGTH characters long. The copied name is NULL-terminated.
432338b8dc3SIngo Weinhold	When you've asked for every name in the list, GetNextAttrName()
433338b8dc3SIngo Weinhold	returns \c B_ENTRY_NOT_FOUND.
434338b8dc3SIngo Weinhold	\param buffer the buffer the name of the next attribute shall be stored in
435338b8dc3SIngo Weinhold		   (must be at least \c B_ATTR_NAME_LENGTH bytes long)
436338b8dc3SIngo Weinhold	\return
437338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
438338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a buffer.
439338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: The object is not initialized.
440338b8dc3SIngo Weinhold	- \c B_ENTRY_NOT_FOUND: There are no more attributes, the last attribute
441338b8dc3SIngo Weinhold	  name has already been returned.
442338b8dc3SIngo Weinhold */
443338b8dc3SIngo Weinholdstatus_t
444338b8dc3SIngo WeinholdBNode::GetNextAttrName(char *buffer)
445338b8dc3SIngo Weinhold{
446338b8dc3SIngo Weinhold	// We're allowed to assume buffer is at least
447338b8dc3SIngo Weinhold	// B_ATTR_NAME_LENGTH chars long, but NULLs
448338b8dc3SIngo Weinhold	// are not acceptable.
449338b8dc3SIngo Weinhold	if (buffer == NULL)
450338b8dc3SIngo Weinhold		return B_BAD_VALUE;	// /new R5 crashed when passed NULL
451338b8dc3SIngo Weinhold	if (InitAttrDir() != B_OK)
452338b8dc3SIngo Weinhold		return B_FILE_ERROR;
453338b8dc3SIngo Weinhold
454338b8dc3SIngo Weinhold	BPrivate::Storage::LongDirEntry entry;
455338b8dc3SIngo Weinhold	ssize_t result = _kern_read_dir(fAttrFd, &entry, sizeof(entry), 1);
456338b8dc3SIngo Weinhold	if (result < 0)
457338b8dc3SIngo Weinhold		return result;
458338b8dc3SIngo Weinhold	if (result == 0)
459338b8dc3SIngo Weinhold		return B_ENTRY_NOT_FOUND;
460338b8dc3SIngo Weinhold	strlcpy(buffer, entry.d_name, B_ATTR_NAME_LENGTH);
461338b8dc3SIngo Weinhold	return B_OK;
462338b8dc3SIngo Weinhold}
463338b8dc3SIngo Weinhold
464338b8dc3SIngo Weinhold/*! \brief Resets the object's attribute pointer to the first attribute in the
465338b8dc3SIngo Weinhold	list.
466338b8dc3SIngo Weinhold	\return
467338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
468338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: Some error occured.
469338b8dc3SIngo Weinhold*/
470338b8dc3SIngo Weinholdstatus_t
471338b8dc3SIngo WeinholdBNode::RewindAttrs()
472338b8dc3SIngo Weinhold{
473338b8dc3SIngo Weinhold	if (InitAttrDir() != B_OK)
474338b8dc3SIngo Weinhold		return B_FILE_ERROR;
475338b8dc3SIngo Weinhold	return _kern_rewind_dir(fAttrFd);
476338b8dc3SIngo Weinhold}
477338b8dc3SIngo Weinhold
478338b8dc3SIngo Weinhold/*!	Writes the specified string to the specified attribute, clobbering any
479338b8dc3SIngo Weinhold	previous data.
480338b8dc3SIngo Weinhold	\param name the name of the attribute
481338b8dc3SIngo Weinhold	\param data the BString to be written to the attribute
482338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
483338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a name or \a data
484338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: The object is not initialized or the node it refers to
485338b8dc3SIngo Weinhold	  is read only.
486338b8dc3SIngo Weinhold	- \c B_NOT_ALLOWED: The node resides on a read only volume.
487338b8dc3SIngo Weinhold	- \c B_DEVICE_FULL: Insufficient disk space.
488338b8dc3SIngo Weinhold	- \c B_NO_MEMORY: Insufficient memory to complete the operation.
489338b8dc3SIngo Weinhold*/
490338b8dc3SIngo Weinholdstatus_t
491338b8dc3SIngo WeinholdBNode::WriteAttrString(const char *name, const BString *data)
492338b8dc3SIngo Weinhold{
493338b8dc3SIngo Weinhold	status_t error = (!name || !data)  ? B_BAD_VALUE : B_OK;
494338b8dc3SIngo Weinhold	if (error == B_OK) {
4958df44a6cSIngo Weinhold		int32 len = data->Length() + 1;
496338b8dc3SIngo Weinhold		ssize_t sizeWritten = WriteAttr(name, B_STRING_TYPE, 0, data->String(),
497338b8dc3SIngo Weinhold										len);
498338b8dc3SIngo Weinhold		if (sizeWritten != len)
499338b8dc3SIngo Weinhold			error = sizeWritten;
500338b8dc3SIngo Weinhold	}
501338b8dc3SIngo Weinhold	return error;
502338b8dc3SIngo Weinhold}
503338b8dc3SIngo Weinhold
504338b8dc3SIngo Weinhold/*!	\brief Reads the data of the specified attribute into the pre-allocated
505338b8dc3SIngo Weinhold		   \a result.
506338b8dc3SIngo Weinhold	\param name the name of the attribute
507338b8dc3SIngo Weinhold	\param result the BString to be set to the value of the attribute
508338b8dc3SIngo Weinhold	\return
509338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
510338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a name or \a result
511338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: The object is not initialized.
512338b8dc3SIngo Weinhold	- \c B_ENTRY_NOT_FOUND: The node has no attribute \a attr.
513338b8dc3SIngo Weinhold*/
514338b8dc3SIngo Weinholdstatus_t
515338b8dc3SIngo WeinholdBNode::ReadAttrString(const char *name, BString *result) const
516338b8dc3SIngo Weinhold{
517338b8dc3SIngo Weinhold	if (!name || !result)
518338b8dc3SIngo Weinhold		return B_BAD_VALUE;
519338b8dc3SIngo Weinhold
520338b8dc3SIngo Weinhold	attr_info info;
521338b8dc3SIngo Weinhold	status_t error;
522338b8dc3SIngo Weinhold
523338b8dc3SIngo Weinhold	error = GetAttrInfo(name, &info);
524338b8dc3SIngo Weinhold	if (error != B_OK)
525338b8dc3SIngo Weinhold		return error;
526338b8dc3SIngo Weinhold	// Lock the string's buffer so we can meddle with it
527338b8dc3SIngo Weinhold	char *data = result->LockBuffer(info.size+1);
528338b8dc3SIngo Weinhold	if (!data)
529338b8dc3SIngo Weinhold		return B_NO_MEMORY;
530338b8dc3SIngo Weinhold	// Read the attribute
531338b8dc3SIngo Weinhold	ssize_t bytes = ReadAttr(name, B_STRING_TYPE, 0, data, info.size);
532338b8dc3SIngo Weinhold	// Check for failure
533338b8dc3SIngo Weinhold	if (bytes < 0) {
534338b8dc3SIngo Weinhold		error = bytes;
535338b8dc3SIngo Weinhold		bytes = 0;	// In this instance, we simply clear the string
536338b8dc3SIngo Weinhold	} else
537338b8dc3SIngo Weinhold		error = B_OK;
538338b8dc3SIngo Weinhold	// Null terminate the new string just to be sure (since it *is*
539338b8dc3SIngo Weinhold	// possible to read and write non-NULL-terminated strings)
540338b8dc3SIngo Weinhold	data[bytes] = 0;
541338b8dc3SIngo Weinhold	result->UnlockBuffer();
542338b8dc3SIngo Weinhold	return error;
543338b8dc3SIngo Weinhold}
544338b8dc3SIngo Weinhold
545338b8dc3SIngo Weinhold/*!	\brief Reinitializes the object as a copy of the \a node.
546338b8dc3SIngo Weinhold	\param node the BNode to be copied
547338b8dc3SIngo Weinhold	\return a reference to this BNode object.
548338b8dc3SIngo Weinhold*/
549338b8dc3SIngo WeinholdBNode&
550338b8dc3SIngo WeinholdBNode::operator=(const BNode &node)
551338b8dc3SIngo Weinhold{
552338b8dc3SIngo Weinhold	// No need to do any assignment if already equal
553338b8dc3SIngo Weinhold	if (*this == node)
554338b8dc3SIngo Weinhold		return *this;
555338b8dc3SIngo Weinhold	// Close down out current state
556338b8dc3SIngo Weinhold	Unset();
557338b8dc3SIngo Weinhold	// We have to manually dup the node, because R5::BNode::Dup()
558338b8dc3SIngo Weinhold	// is not declared to be const (which IMO is retarded).
559338b8dc3SIngo Weinhold	fFd = _kern_dup(node.fFd);
560338b8dc3SIngo Weinhold	fCStatus = (fFd < 0) ? B_NO_INIT : B_OK ;
561338b8dc3SIngo Weinhold	return *this;
562338b8dc3SIngo Weinhold}
563338b8dc3SIngo Weinhold
564338b8dc3SIngo Weinhold/*!	Tests whether this and the supplied BNode object are equal.
565338b8dc3SIngo Weinhold	Two BNode objects are said to be equal if they're set to the same node,
566338b8dc3SIngo Weinhold	or if they're both \c B_NO_INIT.
567338b8dc3SIngo Weinhold	\param node the BNode to be compared with
568338b8dc3SIngo Weinhold	\return \c true, if the BNode objects are equal, \c false otherwise
569338b8dc3SIngo Weinhold*/
570338b8dc3SIngo Weinholdbool
571338b8dc3SIngo WeinholdBNode::operator==(const BNode &node) const
572338b8dc3SIngo Weinhold{
573338b8dc3SIngo Weinhold	if (fCStatus == B_NO_INIT && node.InitCheck() == B_NO_INIT)
574338b8dc3SIngo Weinhold		return true;
575338b8dc3SIngo Weinhold	if (fCStatus == B_OK && node.InitCheck() == B_OK) {
576338b8dc3SIngo Weinhold		// compare the node_refs
577338b8dc3SIngo Weinhold		node_ref ref1, ref2;
578338b8dc3SIngo Weinhold		if (GetNodeRef(&ref1) != B_OK)
579338b8dc3SIngo Weinhold			return false;
580338b8dc3SIngo Weinhold		if (node.GetNodeRef(&ref2) != B_OK)
581338b8dc3SIngo Weinhold			return false;
582338b8dc3SIngo Weinhold		return (ref1 == ref2);
583338b8dc3SIngo Weinhold	}
584338b8dc3SIngo Weinhold	return false;
585338b8dc3SIngo Weinhold}
586338b8dc3SIngo Weinhold
587338b8dc3SIngo Weinhold/*!	Tests whether this and the supplied BNode object are not equal.
588338b8dc3SIngo Weinhold	Two BNode objects are said to be equal if they're set to the same node,
589338b8dc3SIngo Weinhold	or if they're both \c B_NO_INIT.
590338b8dc3SIngo Weinhold	\param node the BNode to be compared with
591338b8dc3SIngo Weinhold	\return \c false, if the BNode objects are equal, \c true otherwise
592338b8dc3SIngo Weinhold*/
593338b8dc3SIngo Weinholdbool
594338b8dc3SIngo WeinholdBNode::operator!=(const BNode &node) const
595338b8dc3SIngo Weinhold{
596338b8dc3SIngo Weinhold	return !(*this == node);
597338b8dc3SIngo Weinhold}
598338b8dc3SIngo Weinhold
599338b8dc3SIngo Weinhold/*!	\brief Returns a POSIX file descriptor to the node this object refers to.
600338b8dc3SIngo Weinhold	Remember to call close() on the file descriptor when you're through with
601338b8dc3SIngo Weinhold	it.
602338b8dc3SIngo Weinhold	\return a valid file descriptor, or -1, if something went wrong.
603338b8dc3SIngo Weinhold*/
604338b8dc3SIngo Weinholdint
605338b8dc3SIngo WeinholdBNode::Dup()
606338b8dc3SIngo Weinhold{
607338b8dc3SIngo Weinhold	int fd = _kern_dup(fFd);
608338b8dc3SIngo Weinhold	return (fd >= 0 ? fd : -1);	// comply with R5 return value
609338b8dc3SIngo Weinhold}
610338b8dc3SIngo Weinhold
611338b8dc3SIngo Weinhold
612338b8dc3SIngo Weinhold/*! (currently unused) */
613338b8dc3SIngo Weinholdvoid BNode::_RudeNode1() { }
614338b8dc3SIngo Weinholdvoid BNode::_RudeNode2() { }
615338b8dc3SIngo Weinholdvoid BNode::_RudeNode3() { }
616338b8dc3SIngo Weinholdvoid BNode::_RudeNode4() { }
617338b8dc3SIngo Weinholdvoid BNode::_RudeNode5() { }
618338b8dc3SIngo Weinholdvoid BNode::_RudeNode6() { }
619338b8dc3SIngo Weinhold
620338b8dc3SIngo Weinhold/*!	\brief Sets the node's file descriptor.
621338b8dc3SIngo Weinhold	Used by each implementation (i.e. BNode, BFile, BDirectory, etc.) to set
622338b8dc3SIngo Weinhold	the node's file descriptor. This allows each subclass to use the various
623338b8dc3SIngo Weinhold	file-type specific system calls for opening file descriptors.
624338b8dc3SIngo Weinhold	\param fd the file descriptor this BNode should be set to (may be -1)
625338b8dc3SIngo Weinhold	\return \c B_OK, if everything went fine, an error code otherwise.
626338b8dc3SIngo Weinhold	\note This method calls close_fd() to close previously opened FDs. Thus
627338b8dc3SIngo Weinhold		  derived classes should take care to first call set_fd() and set
628338b8dc3SIngo Weinhold		  class specific resources freed in their close_fd() version
629338b8dc3SIngo Weinhold		  thereafter.
630338b8dc3SIngo Weinhold*/
631338b8dc3SIngo Weinholdstatus_t
632338b8dc3SIngo WeinholdBNode::set_fd(int fd)
633338b8dc3SIngo Weinhold{
634338b8dc3SIngo Weinhold	if (fFd != -1)
635338b8dc3SIngo Weinhold		close_fd();
636338b8dc3SIngo Weinhold	fFd = fd;
637338b8dc3SIngo Weinhold	return B_OK;
638338b8dc3SIngo Weinhold}
639338b8dc3SIngo Weinhold
640338b8dc3SIngo Weinhold/*!	\brief Closes the node's file descriptor(s).
641338b8dc3SIngo Weinhold	To be implemented by subclasses to close the file descriptor using the
642338b8dc3SIngo Weinhold	proper system call for the given file-type. This implementation calls
643338b8dc3SIngo Weinhold	_kern_close(fFd) and also _kern_close(fAttrDir) if necessary.
644338b8dc3SIngo Weinhold*/
645338b8dc3SIngo Weinholdvoid
646338b8dc3SIngo WeinholdBNode::close_fd()
647338b8dc3SIngo Weinhold{
648338b8dc3SIngo Weinhold	if (fAttrFd >= 0)
649338b8dc3SIngo Weinhold	{
650338b8dc3SIngo Weinhold		_kern_close(fAttrFd);
651338b8dc3SIngo Weinhold		fAttrFd = -1;
652338b8dc3SIngo Weinhold	}
653338b8dc3SIngo Weinhold	if (fFd >= 0) {
654338b8dc3SIngo Weinhold		_kern_close(fFd);
655338b8dc3SIngo Weinhold		fFd = -1;
656338b8dc3SIngo Weinhold	}
657338b8dc3SIngo Weinhold}
658338b8dc3SIngo Weinhold
659338b8dc3SIngo Weinhold// set_status
660338b8dc3SIngo Weinhold/*! \brief Sets the BNode's status.
661338b8dc3SIngo Weinhold	To be used by derived classes instead of accessing the BNode's private
662338b8dc3SIngo Weinhold	\c fCStatus member directly.
663338b8dc3SIngo Weinhold	\param newStatus the new value for the status variable.
664338b8dc3SIngo Weinhold*/
665338b8dc3SIngo Weinholdvoid
666338b8dc3SIngo WeinholdBNode::set_status(status_t newStatus)
667338b8dc3SIngo Weinhold{
668338b8dc3SIngo Weinhold	fCStatus = newStatus;
669338b8dc3SIngo Weinhold}
670338b8dc3SIngo Weinhold
671338b8dc3SIngo Weinhold// _SetTo
672338b8dc3SIngo Weinhold/*!	\brief Initializes the BNode's file descriptor to the node referred to
673338b8dc3SIngo Weinhold		   by the given FD and path combo.
674338b8dc3SIngo Weinhold
675338b8dc3SIngo Weinhold	\a path must either be \c NULL, an absolute or a relative path.
676338b8dc3SIngo Weinhold	In the first case, \a fd must not be \c NULL; the node it refers to will
677338b8dc3SIngo Weinhold	be opened. If absolute, \a fd is ignored. If relative and \a fd is >= 0,
678338b8dc3SIngo Weinhold	it will be reckoned off the directory identified by \a fd, otherwise off
679338b8dc3SIngo Weinhold	the current working directory.
680338b8dc3SIngo Weinhold
681338b8dc3SIngo Weinhold	The method will first try to open the node with read and write permission.
682338b8dc3SIngo Weinhold	If that fails due to a read-only FS or because the user has no write
683338b8dc3SIngo Weinhold	permission for the node, it will re-try opening the node read-only.
684338b8dc3SIngo Weinhold
685338b8dc3SIngo Weinhold	The \a fCStatus member will be set to the return value of this method.
686338b8dc3SIngo Weinhold
687338b8dc3SIngo Weinhold	\param fd Either a directory FD or a value < 0. In the latter case \a path
688338b8dc3SIngo Weinhold		   must be specified.
689338b8dc3SIngo Weinhold	\param path Either \a NULL in which case \a fd must be given, absolute, or
690338b8dc3SIngo Weinhold		   relative to the directory specified by \a fd (if given) or to the
691338b8dc3SIngo Weinhold		   current working directory.
692338b8dc3SIngo Weinhold	\param traverse If the node identified by \a fd and \a path is a symlink
693338b8dc3SIngo Weinhold		   and \a traverse is \c true, the symlink will be resolved recursively.
694338b8dc3SIngo Weinhold	\return \c B_OK, if everything went fine, another error code otherwise.
695338b8dc3SIngo Weinhold*/
696338b8dc3SIngo Weinholdstatus_t
697338b8dc3SIngo WeinholdBNode::_SetTo(int fd, const char *path, bool traverse)
698338b8dc3SIngo Weinhold{
699338b8dc3SIngo Weinhold	Unset();
700338b8dc3SIngo Weinhold	status_t error = (fd >= 0 || path ? B_OK : B_BAD_VALUE);
701338b8dc3SIngo Weinhold	if (error == B_OK) {
702338b8dc3SIngo Weinhold		int traverseFlag = (traverse ? 0 : O_NOTRAVERSE);
703338b8dc3SIngo Weinhold		fFd = _kern_open(fd, path, O_RDWR | traverseFlag, 0);
704338b8dc3SIngo Weinhold		if (fFd < B_OK && fFd != B_ENTRY_NOT_FOUND) {
705338b8dc3SIngo Weinhold			// opening read-write failed, re-try read-only
706338b8dc3SIngo Weinhold			fFd = _kern_open(fd, path, O_RDONLY | traverseFlag, 0);
707338b8dc3SIngo Weinhold		}
708338b8dc3SIngo Weinhold		if (fFd < 0)
709338b8dc3SIngo Weinhold			error = fFd;
710338b8dc3SIngo Weinhold		else
711338b8dc3SIngo Weinhold			fcntl(fFd, F_SETFD, FD_CLOEXEC);
712338b8dc3SIngo Weinhold	}
713338b8dc3SIngo Weinhold	return fCStatus = error;
714338b8dc3SIngo Weinhold}
715338b8dc3SIngo Weinhold
716338b8dc3SIngo Weinhold// _SetTo
717338b8dc3SIngo Weinhold/*!	\brief Initializes the BNode's file descriptor to the node referred to
718338b8dc3SIngo Weinhold		   by the given entry_ref.
719338b8dc3SIngo Weinhold
720338b8dc3SIngo Weinhold	The method will first try to open the node with read and write permission.
721338b8dc3SIngo Weinhold	If that fails due to a read-only FS or because the user has no write
722338b8dc3SIngo Weinhold	permission for the node, it will re-try opening the node read-only.
723338b8dc3SIngo Weinhold
724338b8dc3SIngo Weinhold	The \a fCStatus member will be set to the return value of this method.
725338b8dc3SIngo Weinhold
726338b8dc3SIngo Weinhold	\param ref An entry_ref identifying the node to be opened.
727338b8dc3SIngo Weinhold	\param traverse If the node identified by \a ref is a symlink
728338b8dc3SIngo Weinhold		   and \a traverse is \c true, the symlink will be resolved recursively.
729338b8dc3SIngo Weinhold	\return \c B_OK, if everything went fine, another error code otherwise.
730338b8dc3SIngo Weinhold*/
731338b8dc3SIngo Weinholdstatus_t
732338b8dc3SIngo WeinholdBNode::_SetTo(const entry_ref *ref, bool traverse)
733338b8dc3SIngo Weinhold{
734338b8dc3SIngo Weinhold	Unset();
735338b8dc3SIngo Weinhold	status_t error = (ref ? B_OK : B_BAD_VALUE);
736338b8dc3SIngo Weinhold	if (error == B_OK) {
737338b8dc3SIngo Weinhold		int traverseFlag = (traverse ? 0 : O_NOTRAVERSE);
738338b8dc3SIngo Weinhold		fFd = _kern_open_entry_ref(ref->device, ref->directory, ref->name,
739338b8dc3SIngo Weinhold			O_RDWR | traverseFlag, 0);
740338b8dc3SIngo Weinhold		if (fFd < B_OK && fFd != B_ENTRY_NOT_FOUND) {
741338b8dc3SIngo Weinhold			// opening read-write failed, re-try read-only
742338b8dc3SIngo Weinhold			fFd = _kern_open_entry_ref(ref->device, ref->directory, ref->name,
743338b8dc3SIngo Weinhold				O_RDONLY | traverseFlag, 0);
744338b8dc3SIngo Weinhold		}
745338b8dc3SIngo Weinhold		if (fFd < 0)
746338b8dc3SIngo Weinhold			error = fFd;
747338b8dc3SIngo Weinhold		else
748338b8dc3SIngo Weinhold			fcntl(fFd, F_SETFD, FD_CLOEXEC);
749338b8dc3SIngo Weinhold	}
750338b8dc3SIngo Weinhold	return fCStatus = error;
751338b8dc3SIngo Weinhold}
752338b8dc3SIngo Weinhold
753338b8dc3SIngo Weinhold/*! \brief Modifies a certain setting for this node based on \a what and the
754338b8dc3SIngo Weinhold	corresponding value in \a st.
755338b8dc3SIngo Weinhold	Inherited from and called by BStatable.
756338b8dc3SIngo Weinhold	\param st a stat structure containing the value to be set
757338b8dc3SIngo Weinhold	\param what specifies what setting to be modified
758338b8dc3SIngo Weinhold	\return \c B_OK if everything went fine, an error code otherwise.
759338b8dc3SIngo Weinhold*/
760338b8dc3SIngo Weinholdstatus_t
761338b8dc3SIngo WeinholdBNode::set_stat(struct stat &st, uint32 what)
762338b8dc3SIngo Weinhold{
763338b8dc3SIngo Weinhold	if (fCStatus != B_OK)
764338b8dc3SIngo Weinhold		return B_FILE_ERROR;
765338b8dc3SIngo Weinhold	return _kern_write_stat(fFd, NULL, false, &st, sizeof(struct stat),
766338b8dc3SIngo Weinhold		what);
767338b8dc3SIngo Weinhold}
768338b8dc3SIngo Weinhold
769338b8dc3SIngo Weinhold/*! \brief Verifies that the BNode has been properly initialized, and then
770338b8dc3SIngo Weinhold	(if necessary) opens the attribute directory on the node's file
771338b8dc3SIngo Weinhold	descriptor, storing it in fAttrDir.
772338b8dc3SIngo Weinhold	\return \c B_OK if everything went fine, an error code otherwise.
773338b8dc3SIngo Weinhold*/
774338b8dc3SIngo Weinholdstatus_t
775338b8dc3SIngo WeinholdBNode::InitAttrDir()
776338b8dc3SIngo Weinhold{
777338b8dc3SIngo Weinhold	if (fCStatus == B_OK && fAttrFd < 0) {
778338b8dc3SIngo Weinhold		fAttrFd = _kern_open_attr_dir(fFd, NULL);
779338b8dc3SIngo Weinhold		if (fAttrFd < 0)
780338b8dc3SIngo Weinhold			return fAttrFd;
781338b8dc3SIngo Weinhold
782338b8dc3SIngo Weinhold		// set close on exec flag
783338b8dc3SIngo Weinhold		fcntl(fAttrFd, F_SETFD, FD_CLOEXEC);
784338b8dc3SIngo Weinhold	}
785338b8dc3SIngo Weinhold	return fCStatus;
786338b8dc3SIngo Weinhold}
787338b8dc3SIngo Weinhold
788338b8dc3SIngo Weinhold/*!	\var BNode::fFd
789338b8dc3SIngo Weinhold	File descriptor for the given node.
790338b8dc3SIngo Weinhold*/
791338b8dc3SIngo Weinhold
792338b8dc3SIngo Weinhold/*!	\var BNode::fAttrFd
793338b8dc3SIngo Weinhold	File descriptor for the attribute directory of the node. Initialized lazily.
794338b8dc3SIngo Weinhold*/
795338b8dc3SIngo Weinhold
796338b8dc3SIngo Weinhold/*!	\var BNode::fCStatus
797338b8dc3SIngo Weinhold	The object's initialization status.
798338b8dc3SIngo Weinhold*/
799338b8dc3SIngo Weinhold
800