1338b8dc3SIngo Weinhold//----------------------------------------------------------------------
2338b8dc3SIngo Weinhold//  This software is part of the OpenBeOS distribution and is covered
3b6f76ebeSAugustin Cavalier//  by the MIT License.
4338b8dc3SIngo Weinhold//---------------------------------------------------------------------
5338b8dc3SIngo Weinhold/*!
6338b8dc3SIngo Weinhold	\file Directory.cpp
7338b8dc3SIngo Weinhold	BDirectory implementation.
8338b8dc3SIngo Weinhold*/
9338b8dc3SIngo Weinhold
10338b8dc3SIngo Weinhold#include <fcntl.h>
11338b8dc3SIngo Weinhold#include <string.h>
12338b8dc3SIngo Weinhold
13338b8dc3SIngo Weinhold#include <Directory.h>
14338b8dc3SIngo Weinhold#include <Entry.h>
15338b8dc3SIngo Weinhold#include <File.h>
16338b8dc3SIngo Weinhold#include <fs_info.h>
17338b8dc3SIngo Weinhold#include <Path.h>
18338b8dc3SIngo Weinhold#include <SymLink.h>
19338b8dc3SIngo Weinhold
20338b8dc3SIngo Weinhold#include <syscalls.h>
21338b8dc3SIngo Weinhold
22338b8dc3SIngo Weinhold#include "storage_support.h"
23338b8dc3SIngo Weinhold
24338b8dc3SIngo Weinhold#ifdef USE_OPENBEOS_NAMESPACE
25338b8dc3SIngo Weinholdnamespace OpenBeOS {
26338b8dc3SIngo Weinhold#endif
27338b8dc3SIngo Weinhold
28338b8dc3SIngo Weinhold// constructor
29338b8dc3SIngo Weinhold//! Creates an uninitialized BDirectory object.
30338b8dc3SIngo WeinholdBDirectory::BDirectory()
31338b8dc3SIngo Weinhold		  : BNode(),
32338b8dc3SIngo Weinhold			BEntryList(),
33338b8dc3SIngo Weinhold			fDirFd(-1)
34338b8dc3SIngo Weinhold{
35338b8dc3SIngo Weinhold}
36338b8dc3SIngo Weinhold
37338b8dc3SIngo Weinhold// copy constructor
38338b8dc3SIngo Weinhold//! Creates a copy of the supplied BDirectory.
39338b8dc3SIngo Weinhold/*!	\param dir the BDirectory object to be copied
40338b8dc3SIngo Weinhold*/
41338b8dc3SIngo WeinholdBDirectory::BDirectory(const BDirectory &dir)
42338b8dc3SIngo Weinhold		  : BNode(),
43338b8dc3SIngo Weinhold			BEntryList(),
44338b8dc3SIngo Weinhold			fDirFd(-1)
45338b8dc3SIngo Weinhold{
46338b8dc3SIngo Weinhold	*this = dir;
47338b8dc3SIngo Weinhold}
48338b8dc3SIngo Weinhold
49338b8dc3SIngo Weinhold// constructor
50338b8dc3SIngo Weinhold/*! \brief Creates a BDirectory and initializes it to the directory referred
51338b8dc3SIngo Weinhold	to by the supplied entry_ref.
52338b8dc3SIngo Weinhold	\param ref the entry_ref referring to the directory
53338b8dc3SIngo Weinhold*/
54338b8dc3SIngo WeinholdBDirectory::BDirectory(const entry_ref *ref)
55338b8dc3SIngo Weinhold		  : BNode(),
56338b8dc3SIngo Weinhold			BEntryList(),
57338b8dc3SIngo Weinhold			fDirFd(-1)
58338b8dc3SIngo Weinhold{
59338b8dc3SIngo Weinhold	SetTo(ref);
60338b8dc3SIngo Weinhold}
61338b8dc3SIngo Weinhold
62338b8dc3SIngo Weinhold// constructor
63338b8dc3SIngo Weinhold/*! \brief Creates a BDirectory and initializes it to the directory referred
64338b8dc3SIngo Weinhold	to by the supplied node_ref.
65338b8dc3SIngo Weinhold	\param nref the node_ref referring to the directory
66338b8dc3SIngo Weinhold*/
67338b8dc3SIngo WeinholdBDirectory::BDirectory(const node_ref *nref)
68338b8dc3SIngo Weinhold		  : BNode(),
69338b8dc3SIngo Weinhold			BEntryList(),
70338b8dc3SIngo Weinhold			fDirFd(-1)
71338b8dc3SIngo Weinhold{
72338b8dc3SIngo Weinhold	SetTo(nref);
73338b8dc3SIngo Weinhold}
74338b8dc3SIngo Weinhold
75338b8dc3SIngo Weinhold// constructor
76338b8dc3SIngo Weinhold/*! \brief Creates a BDirectory and initializes it to the directory referred
77338b8dc3SIngo Weinhold	to by the supplied BEntry.
78338b8dc3SIngo Weinhold	\param entry the BEntry referring to the directory
79338b8dc3SIngo Weinhold*/
80338b8dc3SIngo WeinholdBDirectory::BDirectory(const BEntry *entry)
81338b8dc3SIngo Weinhold		  : BNode(),
82338b8dc3SIngo Weinhold			BEntryList(),
83338b8dc3SIngo Weinhold			fDirFd(-1)
84338b8dc3SIngo Weinhold{
85338b8dc3SIngo Weinhold	SetTo(entry);
86338b8dc3SIngo Weinhold}
87338b8dc3SIngo Weinhold
88338b8dc3SIngo Weinhold// constructor
89338b8dc3SIngo Weinhold/*! \brief Creates a BDirectory and initializes it to the directory referred
90338b8dc3SIngo Weinhold	to by the supplied path name.
91338b8dc3SIngo Weinhold	\param path the directory's path name
92338b8dc3SIngo Weinhold*/
93338b8dc3SIngo WeinholdBDirectory::BDirectory(const char *path)
94338b8dc3SIngo Weinhold		  : BNode(),
95338b8dc3SIngo Weinhold			BEntryList(),
96338b8dc3SIngo Weinhold			fDirFd(-1)
97338b8dc3SIngo Weinhold{
98338b8dc3SIngo Weinhold	SetTo(path);
99338b8dc3SIngo Weinhold}
100338b8dc3SIngo Weinhold
101338b8dc3SIngo Weinhold// constructor
102338b8dc3SIngo Weinhold/*! \brief Creates a BDirectory and initializes it to the directory referred
103338b8dc3SIngo Weinhold	to by the supplied path name relative to the specified BDirectory.
104338b8dc3SIngo Weinhold	\param dir the BDirectory, relative to which the directory's path name is
105338b8dc3SIngo Weinhold		   given
106338b8dc3SIngo Weinhold	\param path the directory's path name relative to \a dir
107338b8dc3SIngo Weinhold*/
108338b8dc3SIngo WeinholdBDirectory::BDirectory(const BDirectory *dir, const char *path)
109338b8dc3SIngo Weinhold		  : BNode(),
110338b8dc3SIngo Weinhold			BEntryList(),
111338b8dc3SIngo Weinhold			fDirFd(-1)
112338b8dc3SIngo Weinhold{
113338b8dc3SIngo Weinhold	SetTo(dir, path);
114338b8dc3SIngo Weinhold}
115338b8dc3SIngo Weinhold
116338b8dc3SIngo Weinhold// destructor
117338b8dc3SIngo Weinhold//! Frees all allocated resources.
118338b8dc3SIngo Weinhold/*! If the BDirectory is properly initialized, the directory's file descriptor
119338b8dc3SIngo Weinhold	is closed.
120338b8dc3SIngo Weinhold*/
121338b8dc3SIngo WeinholdBDirectory::~BDirectory()
122338b8dc3SIngo Weinhold{
123338b8dc3SIngo Weinhold	// Also called by the BNode destructor, but we rather try to avoid
124338b8dc3SIngo Weinhold	// problems with calling virtual functions in the base class destructor.
125338b8dc3SIngo Weinhold	// Depending on the compiler implementation an object may be degraded to
126338b8dc3SIngo Weinhold	// an object of the base class after the destructor of the derived class
127338b8dc3SIngo Weinhold	// has been executed.
128338b8dc3SIngo Weinhold	close_fd();
129338b8dc3SIngo Weinhold}
130338b8dc3SIngo Weinhold
131338b8dc3SIngo Weinhold// SetTo
132338b8dc3SIngo Weinhold/*! \brief Re-initializes the BDirectory to the directory referred to by the
133338b8dc3SIngo Weinhold	supplied entry_ref.
134338b8dc3SIngo Weinhold	\param ref the entry_ref referring to the directory
135338b8dc3SIngo Weinhold	\return
136338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
137338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a ref.
138338b8dc3SIngo Weinhold	- \c B_ENTRY_NOT_FOUND: Directory not found.
139338b8dc3SIngo Weinhold	- \c B_PERMISSION_DENIED: Directory permissions didn't allow operation.
140338b8dc3SIngo Weinhold	- \c B_NO_MEMORY: Insufficient memory for operation.
141338b8dc3SIngo Weinhold	- \c B_LINK_LIMIT: Indicates a cyclic loop within the file system.
142338b8dc3SIngo Weinhold	- \c B_BUSY: A node was busy.
143338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: A general file error.
144338b8dc3SIngo Weinhold	- \c B_NO_MORE_FDS: The application has run out of file descriptors.
145338b8dc3SIngo Weinhold*/
146338b8dc3SIngo Weinholdstatus_t
147338b8dc3SIngo WeinholdBDirectory::SetTo(const entry_ref *ref)
148338b8dc3SIngo Weinhold{
149338b8dc3SIngo Weinhold	// open node
150338b8dc3SIngo Weinhold	status_t error = _SetTo(ref, true);
151338b8dc3SIngo Weinhold	if (error != B_OK)
152338b8dc3SIngo Weinhold		return error;
153338b8dc3SIngo Weinhold
154338b8dc3SIngo Weinhold	// open dir
155338b8dc3SIngo Weinhold	error = set_dir_fd(_kern_open_dir_entry_ref(ref->device, ref->directory, ref->name));
156338b8dc3SIngo Weinhold	if (error < 0) {
157338b8dc3SIngo Weinhold		Unset();
158338b8dc3SIngo Weinhold		return (fCStatus = error);
159338b8dc3SIngo Weinhold	}
160338b8dc3SIngo Weinhold
161338b8dc3SIngo Weinhold	// set close on exec flag on dir FD
162338b8dc3SIngo Weinhold	fcntl(fDirFd, F_SETFD, FD_CLOEXEC);
163338b8dc3SIngo Weinhold
164338b8dc3SIngo Weinhold	return B_OK;
165338b8dc3SIngo Weinhold}
166338b8dc3SIngo Weinhold
167338b8dc3SIngo Weinhold// SetTo
168338b8dc3SIngo Weinhold/*! \brief Re-initializes the BDirectory to the directory referred to by the
169338b8dc3SIngo Weinhold	supplied node_ref.
170338b8dc3SIngo Weinhold	\param nref the node_ref referring to the directory
171338b8dc3SIngo Weinhold	\return
172338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
173338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a nref.
174338b8dc3SIngo Weinhold	- \c B_ENTRY_NOT_FOUND: Directory not found.
175338b8dc3SIngo Weinhold	- \c B_PERMISSION_DENIED: Directory permissions didn't allow operation.
176338b8dc3SIngo Weinhold	- \c B_NO_MEMORY: Insufficient memory for operation.
177338b8dc3SIngo Weinhold	- \c B_LINK_LIMIT: Indicates a cyclic loop within the file system.
178338b8dc3SIngo Weinhold	- \c B_BUSY: A node was busy.
179338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: A general file error.
180338b8dc3SIngo Weinhold	- \c B_NO_MORE_FDS: The application has run out of file descriptors.
181338b8dc3SIngo Weinhold*/
182338b8dc3SIngo Weinholdstatus_t
183338b8dc3SIngo WeinholdBDirectory::SetTo(const node_ref *nref)
184338b8dc3SIngo Weinhold{
185338b8dc3SIngo Weinhold	Unset();
186338b8dc3SIngo Weinhold	status_t error = (nref ? B_OK : B_BAD_VALUE);
187338b8dc3SIngo Weinhold	if (error == B_OK) {
188338b8dc3SIngo Weinhold		entry_ref ref(nref->device, nref->node, ".");
189338b8dc3SIngo Weinhold		error = SetTo(&ref);
190338b8dc3SIngo Weinhold	}
191338b8dc3SIngo Weinhold	set_status(error);
192338b8dc3SIngo Weinhold	return error;
193338b8dc3SIngo Weinhold}
194338b8dc3SIngo Weinhold
195338b8dc3SIngo Weinhold// SetTo
196338b8dc3SIngo Weinhold/*! \brief Re-initializes the BDirectory to the directory referred to by the
197338b8dc3SIngo Weinhold	supplied BEntry.
198338b8dc3SIngo Weinhold	\param entry the BEntry referring to the directory
199338b8dc3SIngo Weinhold	\return
200338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
201338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a entry.
202338b8dc3SIngo Weinhold	- \c B_ENTRY_NOT_FOUND: Directory not found.
203338b8dc3SIngo Weinhold	- \c B_PERMISSION_DENIED: Directory permissions didn't allow operation.
204338b8dc3SIngo Weinhold	- \c B_NO_MEMORY: Insufficient memory for operation.
205338b8dc3SIngo Weinhold	- \c B_LINK_LIMIT: Indicates a cyclic loop within the file system.
206338b8dc3SIngo Weinhold	- \c B_BUSY: A node was busy.
207338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: A general file error.
208338b8dc3SIngo Weinhold	- \c B_NO_MORE_FDS: The application has run out of file descriptors.
209338b8dc3SIngo Weinhold*/
210338b8dc3SIngo Weinholdstatus_t
211338b8dc3SIngo WeinholdBDirectory::SetTo(const BEntry *entry)
212338b8dc3SIngo Weinhold{
213338b8dc3SIngo Weinhold	if (!entry) {
214338b8dc3SIngo Weinhold		Unset();
215338b8dc3SIngo Weinhold		return (fCStatus = B_BAD_VALUE);
216338b8dc3SIngo Weinhold	}
217338b8dc3SIngo Weinhold
218338b8dc3SIngo Weinhold	// open node
219338b8dc3SIngo Weinhold	status_t error = _SetTo(entry->fDirFd, entry->fName, true);
220338b8dc3SIngo Weinhold	if (error != B_OK)
221338b8dc3SIngo Weinhold		return error;
222338b8dc3SIngo Weinhold
223338b8dc3SIngo Weinhold	// open dir
224338b8dc3SIngo Weinhold	error = set_dir_fd(_kern_open_dir(entry->fDirFd, entry->fName));
225338b8dc3SIngo Weinhold	if (error < 0) {
226338b8dc3SIngo Weinhold		Unset();
227338b8dc3SIngo Weinhold		return (fCStatus = error);
228338b8dc3SIngo Weinhold	}
229338b8dc3SIngo Weinhold
230338b8dc3SIngo Weinhold	// set close on exec flag on dir FD
231338b8dc3SIngo Weinhold	fcntl(fDirFd, F_SETFD, FD_CLOEXEC);
232338b8dc3SIngo Weinhold
233338b8dc3SIngo Weinhold	return B_OK;
234338b8dc3SIngo Weinhold}
235338b8dc3SIngo Weinhold
236338b8dc3SIngo Weinhold// SetTo
237338b8dc3SIngo Weinhold/*! \brief Re-initializes the BDirectory to the directory referred to by the
238338b8dc3SIngo Weinhold	supplied path name.
239338b8dc3SIngo Weinhold	\param path the directory's path name
240338b8dc3SIngo Weinhold	\return
241338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
242338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a path.
243338b8dc3SIngo Weinhold	- \c B_ENTRY_NOT_FOUND: Directory not found.
244338b8dc3SIngo Weinhold	- \c B_PERMISSION_DENIED: Directory permissions didn't allow operation.
245338b8dc3SIngo Weinhold	- \c B_NO_MEMORY: Insufficient memory for operation.
246338b8dc3SIngo Weinhold	- \c B_NAME_TOO_LONG: The supplied path name (\a path) is too long.
247338b8dc3SIngo Weinhold	- \c B_LINK_LIMIT: Indicates a cyclic loop within the file system.
248338b8dc3SIngo Weinhold	- \c B_BUSY: A node was busy.
249338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: A general file error.
250338b8dc3SIngo Weinhold	- \c B_NO_MORE_FDS: The application has run out of file descriptors.
251338b8dc3SIngo Weinhold	- \c B_NOT_A_DIRECTORY: \a path includes a non-directory.
252338b8dc3SIngo Weinhold*/
253338b8dc3SIngo Weinholdstatus_t
254338b8dc3SIngo WeinholdBDirectory::SetTo(const char *path)
255338b8dc3SIngo Weinhold{
256338b8dc3SIngo Weinhold	// open node
257338b8dc3SIngo Weinhold	status_t error = _SetTo(-1, path, true);
258338b8dc3SIngo Weinhold	if (error != B_OK)
259338b8dc3SIngo Weinhold		return error;
260338b8dc3SIngo Weinhold
261338b8dc3SIngo Weinhold	// open dir
262338b8dc3SIngo Weinhold	error = set_dir_fd(_kern_open_dir(-1, path));
263338b8dc3SIngo Weinhold	if (error < 0) {
264338b8dc3SIngo Weinhold		Unset();
265338b8dc3SIngo Weinhold		return (fCStatus = error);
266338b8dc3SIngo Weinhold	}
267338b8dc3SIngo Weinhold
268338b8dc3SIngo Weinhold	// set close on exec flag on dir FD
269338b8dc3SIngo Weinhold	fcntl(fDirFd, F_SETFD, FD_CLOEXEC);
270338b8dc3SIngo Weinhold
271338b8dc3SIngo Weinhold	return B_OK;
272338b8dc3SIngo Weinhold}
273338b8dc3SIngo Weinhold
274338b8dc3SIngo Weinhold// SetTo
275338b8dc3SIngo Weinhold/*! \brief Re-initializes the BDirectory to the directory referred to by the
276338b8dc3SIngo Weinhold	supplied path name relative to the specified BDirectory.
277338b8dc3SIngo Weinhold	\param dir the BDirectory, relative to which the directory's path name is
278338b8dc3SIngo Weinhold		   given
279338b8dc3SIngo Weinhold	\param path the directory's path name relative to \a dir
280338b8dc3SIngo Weinhold	\return
281338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
282338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a dir or \a path, or \a path is absolute.
283338b8dc3SIngo Weinhold	- \c B_ENTRY_NOT_FOUND: Directory not found.
284338b8dc3SIngo Weinhold	- \c B_PERMISSION_DENIED: Directory permissions didn't allow operation.
285338b8dc3SIngo Weinhold	- \c B_NO_MEMORY: Insufficient memory for operation.
286338b8dc3SIngo Weinhold	- \c B_NAME_TOO_LONG: The supplied path name (\a path) is too long.
287338b8dc3SIngo Weinhold	- \c B_LINK_LIMIT: Indicates a cyclic loop within the file system.
288338b8dc3SIngo Weinhold	- \c B_BUSY: A node was busy.
289338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: A general file error.
290338b8dc3SIngo Weinhold	- \c B_NO_MORE_FDS: The application has run out of file descriptors.
291338b8dc3SIngo Weinhold	- \c B_NOT_A_DIRECTORY: \a path includes a non-directory.
292338b8dc3SIngo Weinhold*/
293338b8dc3SIngo Weinholdstatus_t
294338b8dc3SIngo WeinholdBDirectory::SetTo(const BDirectory *dir, const char *path)
295338b8dc3SIngo Weinhold{
296338b8dc3SIngo Weinhold	if (!dir || !path || BPrivate::Storage::is_absolute_path(path)) {
297338b8dc3SIngo Weinhold		Unset();
298338b8dc3SIngo Weinhold		return (fCStatus = B_BAD_VALUE);
299338b8dc3SIngo Weinhold	}
300338b8dc3SIngo Weinhold
301338b8dc3SIngo Weinhold	// open node
302338b8dc3SIngo Weinhold	status_t error = _SetTo(dir->fDirFd, path, true);
303338b8dc3SIngo Weinhold	if (error != B_OK)
304338b8dc3SIngo Weinhold		return error;
305338b8dc3SIngo Weinhold
306338b8dc3SIngo Weinhold	// open dir
307338b8dc3SIngo Weinhold	error = set_dir_fd(_kern_open_dir(dir->fDirFd, path));
308338b8dc3SIngo Weinhold	if (error < 0) {
309338b8dc3SIngo Weinhold		Unset();
310338b8dc3SIngo Weinhold		return (fCStatus = error);
311338b8dc3SIngo Weinhold	}
312338b8dc3SIngo Weinhold
313338b8dc3SIngo Weinhold	// set close on exec flag on dir FD
314338b8dc3SIngo Weinhold	fcntl(fDirFd, F_SETFD, FD_CLOEXEC);
315338b8dc3SIngo Weinhold
316338b8dc3SIngo Weinhold	return B_OK;
317338b8dc3SIngo Weinhold}
318338b8dc3SIngo Weinhold
319338b8dc3SIngo Weinhold// GetEntry
320338b8dc3SIngo Weinhold//! Returns a BEntry referring to the directory represented by this object.
321338b8dc3SIngo Weinhold/*!	If the initialization of \a entry fails, it is Unset().
322338b8dc3SIngo Weinhold	\param entry a pointer to the entry that shall be set to refer to the
323338b8dc3SIngo Weinhold		   directory
324338b8dc3SIngo Weinhold	\return
325338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
326338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a entry.
327338b8dc3SIngo Weinhold	- \c B_ENTRY_NOT_FOUND: Directory not found.
328338b8dc3SIngo Weinhold	- \c B_PERMISSION_DENIED: Directory permissions didn't allow operation.
329338b8dc3SIngo Weinhold	- \c B_NO_MEMORY: Insufficient memory for operation.
330338b8dc3SIngo Weinhold	- \c B_LINK_LIMIT: Indicates a cyclic loop within the file system.
331338b8dc3SIngo Weinhold	- \c B_BUSY: A node was busy.
332338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: A general file error.
333338b8dc3SIngo Weinhold	- \c B_NO_MORE_FDS: The application has run out of file descriptors.
334338b8dc3SIngo Weinhold*/
335338b8dc3SIngo Weinholdstatus_t
336338b8dc3SIngo WeinholdBDirectory::GetEntry(BEntry *entry) const
337338b8dc3SIngo Weinhold{
338338b8dc3SIngo Weinhold	if (!entry)
339338b8dc3SIngo Weinhold		return B_BAD_VALUE;
340338b8dc3SIngo Weinhold	if (InitCheck() != B_OK)
341338b8dc3SIngo Weinhold		return B_NO_INIT;
342338b8dc3SIngo Weinhold	return entry->SetTo(this, ".", false);
343338b8dc3SIngo Weinhold}
344338b8dc3SIngo Weinhold
345338b8dc3SIngo Weinhold// FindEntry
346338b8dc3SIngo Weinhold/*! \brief Finds an entry referred to by a path relative to the directory
347338b8dc3SIngo Weinhold	represented by this BDirectory.
348338b8dc3SIngo Weinhold	\a path may be absolute. If the BDirectory is not properly initialized,
349338b8dc3SIngo Weinhold	the entry is search relative to the current directory.
350338b8dc3SIngo Weinhold	If the entry couldn't be found, \a entry is Unset().
351338b8dc3SIngo Weinhold	\param path the entry's path name. May be relative to this directory or
352338b8dc3SIngo Weinhold		   absolute.
353338b8dc3SIngo Weinhold	\param entry a pointer to a BEntry to be initialized with the found entry
354338b8dc3SIngo Weinhold	\param traverse specifies whether to follow it, if the found entry
355338b8dc3SIngo Weinhold		   is a symbolic link.
356338b8dc3SIngo Weinhold	\return
357338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
358338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a path or \a entry.
359338b8dc3SIngo Weinhold	- \c B_ENTRY_NOT_FOUND: Entry not found.
360338b8dc3SIngo Weinhold	- \c B_PERMISSION_DENIED: Directory permissions didn't allow operation.
361338b8dc3SIngo Weinhold	- \c B_NO_MEMORY: Insufficient memory for operation.
362338b8dc3SIngo Weinhold	- \c B_NAME_TOO_LONG: The supplied path name (\a path) is too long.
363338b8dc3SIngo Weinhold	- \c B_LINK_LIMIT: Indicates a cyclic loop within the file system.
364338b8dc3SIngo Weinhold	- \c B_BUSY: A node was busy.
365338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: A general file error.
366338b8dc3SIngo Weinhold	- \c B_NO_MORE_FDS: The application has run out of file descriptors.
367338b8dc3SIngo Weinhold	- \c B_NOT_A_DIRECTORY: \a path includes a non-directory.
368338b8dc3SIngo Weinhold	\note The functionality of this method differs from the one of
369338b8dc3SIngo Weinhold		  BEntry::SetTo(BDirectory *, const char *, bool) in that the
370338b8dc3SIngo Weinhold		  latter doesn't require the entry to be existent, whereas this
371338b8dc3SIngo Weinhold		  function does.
372338b8dc3SIngo Weinhold*/
373338b8dc3SIngo Weinholdstatus_t
374338b8dc3SIngo WeinholdBDirectory::FindEntry(const char *path, BEntry *entry, bool traverse) const
375338b8dc3SIngo Weinhold{
376338b8dc3SIngo Weinhold	status_t error = (path && entry ? B_OK : B_BAD_VALUE);
377338b8dc3SIngo Weinhold	if (entry)
378338b8dc3SIngo Weinhold		entry->Unset();
379338b8dc3SIngo Weinhold	if (error == B_OK) {
380338b8dc3SIngo Weinhold		// init a potentially abstract entry
381338b8dc3SIngo Weinhold		if (InitCheck() == B_OK)
382338b8dc3SIngo Weinhold			error = entry->SetTo(this, path, traverse);
383338b8dc3SIngo Weinhold		else
384338b8dc3SIngo Weinhold			error = entry->SetTo(path, traverse);
385338b8dc3SIngo Weinhold		// fail, if entry is abstract
386338b8dc3SIngo Weinhold		if (error == B_OK && !entry->Exists()) {
387338b8dc3SIngo Weinhold			error = B_ENTRY_NOT_FOUND;
388338b8dc3SIngo Weinhold			entry->Unset();
389338b8dc3SIngo Weinhold		}
390338b8dc3SIngo Weinhold	}
391338b8dc3SIngo Weinhold	return error;
392338b8dc3SIngo Weinhold}
393338b8dc3SIngo Weinhold
394338b8dc3SIngo Weinhold// Contains
395338b8dc3SIngo Weinhold/*!	\brief Returns whether this directory or any of its subdirectories
396338b8dc3SIngo Weinhold	at any level contain the entry referred to by the supplied path name.
397338b8dc3SIngo Weinhold	Only entries that match the node flavor specified by \a nodeFlags are
398338b8dc3SIngo Weinhold	considered.
399338b8dc3SIngo Weinhold	If the BDirectory is not properly initialized, the method returns \c false.
400338b8dc3SIngo Weinhold	A non-absolute path is considered relative to the current directory.
401338b8dc3SIngo Weinhold
402338b8dc3SIngo Weinhold	\note R5's implementation always returns \c true given an absolute path or
403338b8dc3SIngo Weinhold	an unitialized directory. This implementation is not compatible with that
404338b8dc3SIngo Weinhold	behavior. Instead it converts the path into a BEntry and passes it to the
405338b8dc3SIngo Weinhold	other version of Contains().
406338b8dc3SIngo Weinhold
407338b8dc3SIngo Weinhold	\param path the entry's path name. May be relative to this directory or
408338b8dc3SIngo Weinhold		   absolute.
409338b8dc3SIngo Weinhold	\param nodeFlags Any of the following:
410338b8dc3SIngo Weinhold		   - \c B_FILE_NODE: The entry must be a file.
411338b8dc3SIngo Weinhold		   - \c B_DIRECTORY_NODE: The entry must be a directory.
412338b8dc3SIngo Weinhold		   - \c B_SYMLINK_NODE: The entry must be a symbolic link.
413338b8dc3SIngo Weinhold		   - \c B_ANY_NODE: The entry may be of any kind.
414338b8dc3SIngo Weinhold	\return
415338b8dc3SIngo Weinhold	- \c true, if the entry exists, its kind does match \nodeFlags and the
416338b8dc3SIngo Weinhold	  BDirectory is properly initialized and does contain the entry at any
417338b8dc3SIngo Weinhold	  level,
418338b8dc3SIngo Weinhold	- \c false, otherwise
419338b8dc3SIngo Weinhold*/
420338b8dc3SIngo Weinholdbool
421338b8dc3SIngo WeinholdBDirectory::Contains(const char *path, int32 nodeFlags) const
422338b8dc3SIngo Weinhold{
423338b8dc3SIngo Weinhold	// check initialization and parameters
424338b8dc3SIngo Weinhold	if (InitCheck() != B_OK)
425338b8dc3SIngo Weinhold		return false;
426338b8dc3SIngo Weinhold	if (!path)
427338b8dc3SIngo Weinhold		return true;	// mimic R5 behavior
428338b8dc3SIngo Weinhold	// turn the path into a BEntry and let the other version do the work
429338b8dc3SIngo Weinhold	BEntry entry;
430338b8dc3SIngo Weinhold	if (BPrivate::Storage::is_absolute_path(path))
431338b8dc3SIngo Weinhold		entry.SetTo(path);
432338b8dc3SIngo Weinhold	else
433338b8dc3SIngo Weinhold		entry.SetTo(this, path);
434338b8dc3SIngo Weinhold	return Contains(&entry, nodeFlags);
435338b8dc3SIngo Weinhold}
436338b8dc3SIngo Weinhold
437338b8dc3SIngo Weinhold// Contains
438338b8dc3SIngo Weinhold/*!	\brief Returns whether this directory or any of its subdirectories
439338b8dc3SIngo Weinhold	at any level contain the entry referred to by the supplied BEntry.
440338b8dc3SIngo Weinhold	Only entries that match the node flavor specified by \a nodeFlags are
441338b8dc3SIngo Weinhold	considered.
442338b8dc3SIngo Weinhold	\param entry a BEntry referring to the entry
443338b8dc3SIngo Weinhold	\param nodeFlags Any of the following:
444338b8dc3SIngo Weinhold		   - \c B_FILE_NODE: The entry must be a file.
445338b8dc3SIngo Weinhold		   - \c B_DIRECTORY_NODE: The entry must be a directory.
446338b8dc3SIngo Weinhold		   - \c B_SYMLINK_NODE: The entry must be a symbolic link.
447338b8dc3SIngo Weinhold		   - \c B_ANY_NODE: The entry may be of any kind.
448338b8dc3SIngo Weinhold	\return
449338b8dc3SIngo Weinhold	- \c true, if the BDirectory is properly initialized and the entry of the
450338b8dc3SIngo Weinhold	  matching kind could be found,
451338b8dc3SIngo Weinhold	- \c false, otherwise
452338b8dc3SIngo Weinhold*/
453338b8dc3SIngo Weinholdbool
454338b8dc3SIngo WeinholdBDirectory::Contains(const BEntry *entry, int32 nodeFlags) const
455338b8dc3SIngo Weinhold{
456338b8dc3SIngo Weinhold	bool result = (entry);
457338b8dc3SIngo Weinhold	// check, if the entry exists at all
458338b8dc3SIngo Weinhold	if (result)
459338b8dc3SIngo Weinhold		result = entry->Exists();
460338b8dc3SIngo Weinhold	// test the node kind
461338b8dc3SIngo Weinhold	if (result) {
462338b8dc3SIngo Weinhold		switch (nodeFlags) {
463338b8dc3SIngo Weinhold			case B_FILE_NODE:
464338b8dc3SIngo Weinhold				result = entry->IsFile();
465338b8dc3SIngo Weinhold				break;
466338b8dc3SIngo Weinhold			case B_DIRECTORY_NODE:
467338b8dc3SIngo Weinhold				result = entry->IsDirectory();
468338b8dc3SIngo Weinhold				break;
469338b8dc3SIngo Weinhold			case B_SYMLINK_NODE:
470338b8dc3SIngo Weinhold				result = entry->IsSymLink();
471338b8dc3SIngo Weinhold				break;
472338b8dc3SIngo Weinhold			case B_ANY_NODE:
473338b8dc3SIngo Weinhold				break;
474338b8dc3SIngo Weinhold			default:
475338b8dc3SIngo Weinhold				result = false;
476338b8dc3SIngo Weinhold				break;
477338b8dc3SIngo Weinhold		}
478338b8dc3SIngo Weinhold	}
479338b8dc3SIngo Weinhold	// If the directory is initialized, get the canonical paths of the dir and
480338b8dc3SIngo Weinhold	// the entry and check, if the latter is a prefix of the first one.
481338b8dc3SIngo Weinhold	if (result && InitCheck() == B_OK) {
482338b8dc3SIngo Weinhold		BPath dirPath(this, ".", true);
483338b8dc3SIngo Weinhold		BPath entryPath(entry);
484338b8dc3SIngo Weinhold		if (dirPath.InitCheck() == B_OK && entryPath.InitCheck() == B_OK) {
485338b8dc3SIngo Weinhold			result = !strncmp(dirPath.Path(), entryPath.Path(),
486338b8dc3SIngo Weinhold				strlen(dirPath.Path()));
487338b8dc3SIngo Weinhold		} else
488338b8dc3SIngo Weinhold			result = false;
489338b8dc3SIngo Weinhold	}
490338b8dc3SIngo Weinhold	return result;
491338b8dc3SIngo Weinhold}
492338b8dc3SIngo Weinhold
493338b8dc3SIngo Weinhold// GetStatFor
494338b8dc3SIngo Weinhold/*!	\brief Returns the stat structure of the entry referred to by the supplied
495338b8dc3SIngo Weinhold	path name.
496338b8dc3SIngo Weinhold	\param path the entry's path name. May be relative to this directory or
497338b8dc3SIngo Weinhold		   absolute, or \c NULL to get the directories stat info.
498338b8dc3SIngo Weinhold	\param st a pointer to the stat structure to be filled in by this function
499338b8dc3SIngo Weinhold	\return
500338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
501338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a st.
502338b8dc3SIngo Weinhold	- \c B_ENTRY_NOT_FOUND: Entry not found.
503338b8dc3SIngo Weinhold	- \c B_PERMISSION_DENIED: Directory permissions didn't allow operation.
504338b8dc3SIngo Weinhold	- \c B_NO_MEMORY: Insufficient memory for operation.
505338b8dc3SIngo Weinhold	- \c B_NAME_TOO_LONG: The supplied path name (\a path) is too long.
506338b8dc3SIngo Weinhold	- \c B_LINK_LIMIT: Indicates a cyclic loop within the file system.
507338b8dc3SIngo Weinhold	- \c B_BUSY: A node was busy.
508338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: A general file error.
509338b8dc3SIngo Weinhold	- \c B_NO_MORE_FDS: The application has run out of file descriptors.
510338b8dc3SIngo Weinhold	- \c B_NOT_A_DIRECTORY: \a path includes a non-directory.
511338b8dc3SIngo Weinhold*/
512338b8dc3SIngo Weinholdstatus_t
513338b8dc3SIngo WeinholdBDirectory::GetStatFor(const char *path, struct stat *st) const
514338b8dc3SIngo Weinhold{
515338b8dc3SIngo Weinhold	if (!st)
516338b8dc3SIngo Weinhold		return B_BAD_VALUE;
517338b8dc3SIngo Weinhold	if (InitCheck() != B_OK)
518338b8dc3SIngo Weinhold		return B_NO_INIT;
519338b8dc3SIngo Weinhold	status_t error = B_OK;
520338b8dc3SIngo Weinhold	if (path) {
521338b8dc3SIngo Weinhold		if (strlen(path) == 0)
522338b8dc3SIngo Weinhold			return B_ENTRY_NOT_FOUND;
523338b8dc3SIngo Weinhold		error = _kern_read_stat(fDirFd, path, false, st, sizeof(struct stat));
524338b8dc3SIngo Weinhold	} else
525338b8dc3SIngo Weinhold		error = GetStat(st);
526338b8dc3SIngo Weinhold	return error;
527338b8dc3SIngo Weinhold}
528338b8dc3SIngo Weinhold
529338b8dc3SIngo Weinhold// GetNextEntry
530338b8dc3SIngo Weinhold//! Returns the BDirectory's next entry as a BEntry.
531338b8dc3SIngo Weinhold/*!	Unlike GetNextDirents() this method ignores the entries "." and "..".
532338b8dc3SIngo Weinhold	\param entry a pointer to a BEntry to be initialized to the found entry
533338b8dc3SIngo Weinhold	\param traverse specifies whether to follow it, if the found entry
534338b8dc3SIngo Weinhold		   is a symbolic link.
535338b8dc3SIngo Weinhold	\note The iterator used by this method is the same one used by
536338b8dc3SIngo Weinhold		  GetNextRef(), GetNextDirents(), Rewind() and CountEntries().
537338b8dc3SIngo Weinhold	\return
538338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
539338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a entry.
540338b8dc3SIngo Weinhold	- \c B_ENTRY_NOT_FOUND: No more entries found.
541338b8dc3SIngo Weinhold	- \c B_PERMISSION_DENIED: Directory permissions didn't allow operation.
542338b8dc3SIngo Weinhold	- \c B_NO_MEMORY: Insufficient memory for operation.
543338b8dc3SIngo Weinhold	- \c B_LINK_LIMIT: Indicates a cyclic loop within the file system.
544338b8dc3SIngo Weinhold	- \c B_BUSY: A node was busy.
545338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: A general file error.
546338b8dc3SIngo Weinhold	- \c B_NO_MORE_FDS: The application has run out of file descriptors.
547338b8dc3SIngo Weinhold*/
548338b8dc3SIngo Weinholdstatus_t
549338b8dc3SIngo WeinholdBDirectory::GetNextEntry(BEntry *entry, bool traverse)
550338b8dc3SIngo Weinhold{
551338b8dc3SIngo Weinhold	status_t error = (entry ? B_OK : B_BAD_VALUE);
552338b8dc3SIngo Weinhold	if (error == B_OK) {
553338b8dc3SIngo Weinhold		entry_ref ref;
554338b8dc3SIngo Weinhold		error = GetNextRef(&ref);
555338b8dc3SIngo Weinhold		if (error == B_OK)
556338b8dc3SIngo Weinhold			error = entry->SetTo(&ref, traverse);
557338b8dc3SIngo Weinhold	}
558338b8dc3SIngo Weinhold	return error;
559338b8dc3SIngo Weinhold}
560338b8dc3SIngo Weinhold
561338b8dc3SIngo Weinhold// GetNextRef
562338b8dc3SIngo Weinhold//! Returns the BDirectory's next entry as an entry_ref.
563338b8dc3SIngo Weinhold/*!	Unlike GetNextDirents() this method ignores the entries "." and "..".
564338b8dc3SIngo Weinhold	\param ref a pointer to an entry_ref to be filled in with the data of the
565338b8dc3SIngo Weinhold		   found entry
566338b8dc3SIngo Weinhold	\param traverse specifies whether to follow it, if the found entry
567338b8dc3SIngo Weinhold		   is a symbolic link.
568338b8dc3SIngo Weinhold	\note The iterator used be this method is the same one used by
569338b8dc3SIngo Weinhold		  GetNextEntry(), GetNextDirents(), Rewind() and CountEntries().
570338b8dc3SIngo Weinhold	\return
571338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
572338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a ref.
573338b8dc3SIngo Weinhold	- \c B_ENTRY_NOT_FOUND: No more entries found.
574338b8dc3SIngo Weinhold	- \c B_PERMISSION_DENIED: Directory permissions didn't allow operation.
575338b8dc3SIngo Weinhold	- \c B_NO_MEMORY: Insufficient memory for operation.
576338b8dc3SIngo Weinhold	- \c B_LINK_LIMIT: Indicates a cyclic loop within the file system.
577338b8dc3SIngo Weinhold	- \c B_BUSY: A node was busy.
578338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: A general file error.
579338b8dc3SIngo Weinhold	- \c B_NO_MORE_FDS: The application has run out of file descriptors.
580338b8dc3SIngo Weinhold*/
581338b8dc3SIngo Weinholdstatus_t
582338b8dc3SIngo WeinholdBDirectory::GetNextRef(entry_ref *ref)
583338b8dc3SIngo Weinhold{
584338b8dc3SIngo Weinhold	status_t error = (ref ? B_OK : B_BAD_VALUE);
585338b8dc3SIngo Weinhold	if (error == B_OK && InitCheck() != B_OK)
586338b8dc3SIngo Weinhold		error = B_FILE_ERROR;
587338b8dc3SIngo Weinhold	if (error == B_OK) {
588338b8dc3SIngo Weinhold		BPrivate::Storage::LongDirEntry entry;
589338b8dc3SIngo Weinhold		bool next = true;
590338b8dc3SIngo Weinhold		while (error == B_OK && next) {
591338b8dc3SIngo Weinhold			if (GetNextDirents(&entry, sizeof(entry), 1) != 1) {
592338b8dc3SIngo Weinhold				error = B_ENTRY_NOT_FOUND;
593338b8dc3SIngo Weinhold			} else {
594338b8dc3SIngo Weinhold				next = (!strcmp(entry.d_name, ".")
595338b8dc3SIngo Weinhold						|| !strcmp(entry.d_name, ".."));
596338b8dc3SIngo Weinhold			}
597338b8dc3SIngo Weinhold		}
598338b8dc3SIngo Weinhold		if (error == B_OK) {
599338b8dc3SIngo Weinhold			ref->device = fDirNodeRef.device;
600338b8dc3SIngo Weinhold			ref->directory = fDirNodeRef.node;
601338b8dc3SIngo Weinhold			error = ref->set_name(entry.d_name);
602338b8dc3SIngo Weinhold		}
603338b8dc3SIngo Weinhold	}
604338b8dc3SIngo Weinhold	return error;
605338b8dc3SIngo Weinhold}
606338b8dc3SIngo Weinhold
607338b8dc3SIngo Weinhold// GetNextDirents
608338b8dc3SIngo Weinhold//! Returns the BDirectory's next entries as dirent structures.
609338b8dc3SIngo Weinhold/*!	Unlike GetNextEntry() and GetNextRef(), this method returns also
610338b8dc3SIngo Weinhold	the entries "." and "..".
611338b8dc3SIngo Weinhold	\param buf a pointer to a buffer to be filled with dirent structures of
612338b8dc3SIngo Weinhold		   the found entries
613338b8dc3SIngo Weinhold	\param count the maximal number of entries to be returned.
614338b8dc3SIngo Weinhold	\note The iterator used by this method is the same one used by
615338b8dc3SIngo Weinhold		  GetNextEntry(), GetNextRef(), Rewind() and CountEntries().
616338b8dc3SIngo Weinhold	\return
617338b8dc3SIngo Weinhold	- The number of dirent structures stored in the buffer, 0 when there are
618338b8dc3SIngo Weinhold	  no more entries to be returned.
619338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a buf.
620338b8dc3SIngo Weinhold	- \c B_PERMISSION_DENIED: Directory permissions didn't allow operation.
621338b8dc3SIngo Weinhold	- \c B_NO_MEMORY: Insufficient memory for operation.
622338b8dc3SIngo Weinhold	- \c B_NAME_TOO_LONG: The entry's name is too long for the buffer.
623338b8dc3SIngo Weinhold	- \c B_LINK_LIMIT: Indicates a cyclic loop within the file system.
624338b8dc3SIngo Weinhold	- \c B_BUSY: A node was busy.
625338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: A general file error.
626338b8dc3SIngo Weinhold	- \c B_NO_MORE_FDS: The application has run out of file descriptors.
627338b8dc3SIngo Weinhold*/
628338b8dc3SIngo Weinholdint32
629338b8dc3SIngo WeinholdBDirectory::GetNextDirents(dirent *buf, size_t bufSize, int32 count)
630338b8dc3SIngo Weinhold{
631338b8dc3SIngo Weinhold	if (!buf)
632338b8dc3SIngo Weinhold		return B_BAD_VALUE;
633338b8dc3SIngo Weinhold	if (InitCheck() != B_OK)
634338b8dc3SIngo Weinhold		return B_FILE_ERROR;
635338b8dc3SIngo Weinhold	return _kern_read_dir(fDirFd, buf, bufSize, count);
636338b8dc3SIngo Weinhold}
637338b8dc3SIngo Weinhold
638338b8dc3SIngo Weinhold// Rewind
639338b8dc3SIngo Weinhold//!	Rewinds the directory iterator.
640338b8dc3SIngo Weinhold/*!	\return
641338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
642338b8dc3SIngo Weinhold	- \c B_PERMISSION_DENIED: Directory permissions didn't allow operation.
643338b8dc3SIngo Weinhold	- \c B_NO_MEMORY: Insufficient memory for operation.
644338b8dc3SIngo Weinhold	- \c B_LINK_LIMIT: Indicates a cyclic loop within the file system.
645338b8dc3SIngo Weinhold	- \c B_BUSY: A node was busy.
646338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: A general file error.
647338b8dc3SIngo Weinhold	- \c B_NO_MORE_FDS: The application has run out of file descriptors.
648338b8dc3SIngo Weinhold	\see GetNextEntry(), GetNextRef(), GetNextDirents(), CountEntries()
649338b8dc3SIngo Weinhold*/
650338b8dc3SIngo Weinholdstatus_t
651338b8dc3SIngo WeinholdBDirectory::Rewind()
652338b8dc3SIngo Weinhold{
653338b8dc3SIngo Weinhold	if (InitCheck() != B_OK)
654338b8dc3SIngo Weinhold		return B_FILE_ERROR;
655338b8dc3SIngo Weinhold	return _kern_rewind_dir(fDirFd);
656338b8dc3SIngo Weinhold}
657338b8dc3SIngo Weinhold
658338b8dc3SIngo Weinhold// CountEntries
659338b8dc3SIngo Weinhold//!	Returns the number of entries in this directory.
660338b8dc3SIngo Weinhold/*!	CountEntries() uses the directory iterator also used by GetNextEntry(),
661338b8dc3SIngo Weinhold	GetNextRef() and GetNextDirents(). It does a Rewind(), iterates through
662338b8dc3SIngo Weinhold	the entries and Rewind()s again. The entries "." and ".." are not counted.
663338b8dc3SIngo Weinhold	\return
664338b8dc3SIngo Weinhold	- the number of entries in the directory (not counting "." and "..").
665338b8dc3SIngo Weinhold	- \c B_PERMISSION_DENIED: Directory permissions didn't allow operation.
666338b8dc3SIngo Weinhold	- \c B_NO_MEMORY: Insufficient memory for operation.
667338b8dc3SIngo Weinhold	- \c B_LINK_LIMIT: Indicates a cyclic loop within the file system.
668338b8dc3SIngo Weinhold	- \c B_BUSY: A node was busy.
669338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: A general file error.
670338b8dc3SIngo Weinhold	- \c B_NO_MORE_FDS: The application has run out of file descriptors.
671338b8dc3SIngo Weinhold	\see GetNextEntry(), GetNextRef(), GetNextDirents(), Rewind()
672338b8dc3SIngo Weinhold*/
673338b8dc3SIngo Weinholdint32
674338b8dc3SIngo WeinholdBDirectory::CountEntries()
675338b8dc3SIngo Weinhold{
676338b8dc3SIngo Weinhold	status_t error = Rewind();
677338b8dc3SIngo Weinhold	if (error != B_OK)
678338b8dc3SIngo Weinhold		return error;
679338b8dc3SIngo Weinhold	int32 count = 0;
680338b8dc3SIngo Weinhold	BPrivate::Storage::LongDirEntry entry;
681338b8dc3SIngo Weinhold	while (error == B_OK) {
682338b8dc3SIngo Weinhold		if (GetNextDirents(&entry, sizeof(entry), 1) != 1)
683338b8dc3SIngo Weinhold			break;
684338b8dc3SIngo Weinhold		if (strcmp(entry.d_name, ".") != 0 && strcmp(entry.d_name, "..") != 0)
685338b8dc3SIngo Weinhold			count++;
686338b8dc3SIngo Weinhold	}
687338b8dc3SIngo Weinhold	Rewind();
688338b8dc3SIngo Weinhold	return (error == B_OK ? count : error);
689338b8dc3SIngo Weinhold}
690338b8dc3SIngo Weinhold
691338b8dc3SIngo Weinhold// CreateDirectory
692338b8dc3SIngo Weinhold//! Creates a new directory.
693338b8dc3SIngo Weinhold/*! If an entry with the supplied name does already exist, the method fails.
694338b8dc3SIngo Weinhold	\param path the new directory's path name. May be relative to this
695338b8dc3SIngo Weinhold		   directory or absolute.
696338b8dc3SIngo Weinhold	\param dir a pointer to a BDirectory to be initialized to the newly
697338b8dc3SIngo Weinhold		   created directory. May be \c NULL.
698338b8dc3SIngo Weinhold	\return
699338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
700338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a path.
701338b8dc3SIngo Weinhold	- \c B_ENTRY_NOT_FOUND: \a path does not refer to a possible entry.
702338b8dc3SIngo Weinhold	- \c B_PERMISSION_DENIED: Directory permissions didn't allow operation.
703338b8dc3SIngo Weinhold	- \c B_NO_MEMORY: Insufficient memory for operation.
704338b8dc3SIngo Weinhold	- \c B_LINK_LIMIT: Indicates a cyclic loop within the file system.
705338b8dc3SIngo Weinhold	- \c B_BUSY: A node was busy.
706338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: A general file error.
707338b8dc3SIngo Weinhold	- \c B_FILE_EXISTS: An entry with that name does already exist.
708338b8dc3SIngo Weinhold	- \c B_NO_MORE_FDS: The application has run out of file descriptors.
709338b8dc3SIngo Weinhold*/
710338b8dc3SIngo Weinholdstatus_t
711338b8dc3SIngo WeinholdBDirectory::CreateDirectory(const char *path, BDirectory *dir)
712338b8dc3SIngo Weinhold{
713338b8dc3SIngo Weinhold	if (!path)
714338b8dc3SIngo Weinhold		return B_BAD_VALUE;
715338b8dc3SIngo Weinhold	// create the dir
716338b8dc3SIngo Weinhold	status_t error = _kern_create_dir(fDirFd, path,
717338b8dc3SIngo Weinhold		S_IRWXU | S_IRWXG | S_IRWXU);
718338b8dc3SIngo Weinhold	if (error != B_OK)
719338b8dc3SIngo Weinhold		return error;
720338b8dc3SIngo Weinhold	if (!dir)
721338b8dc3SIngo Weinhold		return B_OK;
722338b8dc3SIngo Weinhold	// init the supplied BDirectory
723338b8dc3SIngo Weinhold	if (InitCheck() != B_OK || BPrivate::Storage::is_absolute_path(path))
724338b8dc3SIngo Weinhold		return dir->SetTo(path);
725338b8dc3SIngo Weinhold	else
726338b8dc3SIngo Weinhold		return dir->SetTo(this, path);
727338b8dc3SIngo Weinhold}
728338b8dc3SIngo Weinhold
729338b8dc3SIngo Weinhold// CreateFile
730338b8dc3SIngo Weinhold//! Creates a new file.
731338b8dc3SIngo Weinhold/*!	If a file with the supplied name does already exist, the method fails,
732338b8dc3SIngo Weinhold	unless it is passed \c false to \a failIfExists -- in that case the file
733338b8dc3SIngo Weinhold	is truncated to zero size. The new BFile will operate in \c B_READ_WRITE
734338b8dc3SIngo Weinhold	mode.
735338b8dc3SIngo Weinhold	\param path the new file's path name. May be relative to this
736338b8dc3SIngo Weinhold		   directory or absolute.
737338b8dc3SIngo Weinhold	\param file a pointer to a BFile to be initialized to the newly
738338b8dc3SIngo Weinhold		   created file. May be \c NULL.
739338b8dc3SIngo Weinhold	\param failIfExists \c true, if the method should fail when the file
740338b8dc3SIngo Weinhold		   already exists, \c false otherwise
741338b8dc3SIngo Weinhold	\return
742338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
743338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a path.
744338b8dc3SIngo Weinhold	- \c B_ENTRY_NOT_FOUND: \a path does not refer to a possible entry.
745338b8dc3SIngo Weinhold	- \c B_PERMISSION_DENIED: Directory permissions didn't allow operation.
746338b8dc3SIngo Weinhold	- \c B_NO_MEMORY: Insufficient memory for operation.
747338b8dc3SIngo Weinhold	- \c B_LINK_LIMIT: Indicates a cyclic loop within the file system.
748338b8dc3SIngo Weinhold	- \c B_BUSY: A node was busy.
749338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: A general file error.
750338b8dc3SIngo Weinhold	- \c B_FILE_EXISTS: A file with that name does already exist and
751338b8dc3SIngo Weinhold	  \c true has been passed for \a failIfExists.
752338b8dc3SIngo Weinhold	- \c B_IS_A_DIRECTORY: A directory with the supplied name does already
753338b8dc3SIngo Weinhold	  exist.
754338b8dc3SIngo Weinhold	- \c B_NO_MORE_FDS: The application has run out of file descriptors.
755338b8dc3SIngo Weinhold*/
756338b8dc3SIngo Weinholdstatus_t
757338b8dc3SIngo WeinholdBDirectory::CreateFile(const char *path, BFile *file, bool failIfExists)
758338b8dc3SIngo Weinhold{
759338b8dc3SIngo Weinhold	if (!path)
760338b8dc3SIngo Weinhold		return B_BAD_VALUE;
761338b8dc3SIngo Weinhold	// Let BFile do the dirty job.
762338b8dc3SIngo Weinhold	uint32 openMode = B_READ_WRITE | B_CREATE_FILE
763338b8dc3SIngo Weinhold					  | (failIfExists ? B_FAIL_IF_EXISTS : 0);
764338b8dc3SIngo Weinhold	BFile tmpFile;
765338b8dc3SIngo Weinhold	BFile *realFile = (file ? file : &tmpFile);
766338b8dc3SIngo Weinhold	status_t error = B_OK;
767338b8dc3SIngo Weinhold	if (InitCheck() == B_OK && !BPrivate::Storage::is_absolute_path(path))
768338b8dc3SIngo Weinhold		error = realFile->SetTo(this, path, openMode);
769338b8dc3SIngo Weinhold	else
770338b8dc3SIngo Weinhold		error = realFile->SetTo(path, openMode);
771338b8dc3SIngo Weinhold	if (error != B_OK && file) // mimic R5 behavior
772338b8dc3SIngo Weinhold		file->Unset();
773338b8dc3SIngo Weinhold	return error;
774338b8dc3SIngo Weinhold}
775338b8dc3SIngo Weinhold
776338b8dc3SIngo Weinhold// CreateSymLink
777338b8dc3SIngo Weinhold//! Creates a new symbolic link.
778338b8dc3SIngo Weinhold/*! If an entry with the supplied name does already exist, the method fails.
779338b8dc3SIngo Weinhold	\param path the new symbolic link's path name. May be relative to this
780338b8dc3SIngo Weinhold		   directory or absolute.
781338b8dc3SIngo Weinhold	\param linkToPath the path the symbolic link shall point to.
782338b8dc3SIngo Weinhold	\param dir a pointer to a BSymLink to be initialized to the newly
783338b8dc3SIngo Weinhold		   created symbolic link. May be \c NULL.
784338b8dc3SIngo Weinhold	\return
785338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
786338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a path or \a linkToPath.
787338b8dc3SIngo Weinhold	- \c B_ENTRY_NOT_FOUND: \a path does not refer to a possible entry.
788338b8dc3SIngo Weinhold	- \c B_PERMISSION_DENIED: Directory permissions didn't allow operation.
789338b8dc3SIngo Weinhold	- \c B_NO_MEMORY: Insufficient memory for operation.
790338b8dc3SIngo Weinhold	- \c B_LINK_LIMIT: Indicates a cyclic loop within the file system.
791338b8dc3SIngo Weinhold	- \c B_BUSY: A node was busy.
792338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: A general file error.
793338b8dc3SIngo Weinhold	- \c B_FILE_EXISTS: An entry with that name does already exist.
794338b8dc3SIngo Weinhold	- \c B_NO_MORE_FDS: The application has run out of file descriptors.
795338b8dc3SIngo Weinhold*/
796338b8dc3SIngo Weinholdstatus_t
797338b8dc3SIngo WeinholdBDirectory::CreateSymLink(const char *path, const char *linkToPath,
798338b8dc3SIngo Weinhold						  BSymLink *link)
799338b8dc3SIngo Weinhold{
800338b8dc3SIngo Weinhold	if (!path || !linkToPath)
801338b8dc3SIngo Weinhold		return B_BAD_VALUE;
802338b8dc3SIngo Weinhold	// create the symlink
803338b8dc3SIngo Weinhold	status_t error = _kern_create_symlink(fDirFd, path, linkToPath,
804338b8dc3SIngo Weinhold		S_IRWXU | S_IRWXG | S_IRWXU);
805338b8dc3SIngo Weinhold	if (error != B_OK)
806338b8dc3SIngo Weinhold		return error;
807338b8dc3SIngo Weinhold	if (!link)
808338b8dc3SIngo Weinhold		return B_OK;
809338b8dc3SIngo Weinhold	// init the supplied BSymLink
810338b8dc3SIngo Weinhold	if (InitCheck() != B_OK || BPrivate::Storage::is_absolute_path(path))
811338b8dc3SIngo Weinhold		return link->SetTo(path);
812338b8dc3SIngo Weinhold	else
813338b8dc3SIngo Weinhold		return link->SetTo(this, path);
814338b8dc3SIngo Weinhold}
815338b8dc3SIngo Weinhold
816338b8dc3SIngo Weinhold// =
817338b8dc3SIngo Weinhold//! Assigns another BDirectory to this BDirectory.
818338b8dc3SIngo Weinhold/*!	If the other BDirectory is uninitialized, this one wi'll be too. Otherwise
819338b8dc3SIngo Weinhold	it will refer to the same directory, unless an error occurs.
820338b8dc3SIngo Weinhold	\param dir the original BDirectory
821338b8dc3SIngo Weinhold	\return a reference to this BDirectory
822338b8dc3SIngo Weinhold*/
823338b8dc3SIngo WeinholdBDirectory &
824338b8dc3SIngo WeinholdBDirectory::operator=(const BDirectory &dir)
825338b8dc3SIngo Weinhold{
826338b8dc3SIngo Weinhold	if (&dir != this) {	// no need to assign us to ourselves
827338b8dc3SIngo Weinhold		Unset();
828338b8dc3SIngo Weinhold		if (dir.InitCheck() == B_OK)
829338b8dc3SIngo Weinhold			SetTo(&dir, ".");
830338b8dc3SIngo Weinhold	}
831338b8dc3SIngo Weinhold	return *this;
832338b8dc3SIngo Weinhold}
833338b8dc3SIngo Weinhold
834338b8dc3SIngo Weinhold
835338b8dc3SIngo Weinhold// FBC
836338b8dc3SIngo Weinholdvoid BDirectory::_ErectorDirectory1() {}
837338b8dc3SIngo Weinholdvoid BDirectory::_ErectorDirectory2() {}
838338b8dc3SIngo Weinholdvoid BDirectory::_ErectorDirectory3() {}
839338b8dc3SIngo Weinholdvoid BDirectory::_ErectorDirectory4() {}
840338b8dc3SIngo Weinholdvoid BDirectory::_ErectorDirectory5() {}
841338b8dc3SIngo Weinholdvoid BDirectory::_ErectorDirectory6() {}
842338b8dc3SIngo Weinhold
843338b8dc3SIngo Weinhold// close_fd
844338b8dc3SIngo Weinhold//! Closes the BDirectory's file descriptor.
845338b8dc3SIngo Weinholdvoid
846338b8dc3SIngo WeinholdBDirectory::close_fd()
847338b8dc3SIngo Weinhold{
848338b8dc3SIngo Weinhold	if (fDirFd >= 0) {
849338b8dc3SIngo Weinhold		_kern_close(fDirFd);
850338b8dc3SIngo Weinhold		fDirFd = -1;
851338b8dc3SIngo Weinhold	}
852338b8dc3SIngo Weinhold	BNode::close_fd();
853338b8dc3SIngo Weinhold}
854338b8dc3SIngo Weinhold
855338b8dc3SIngo Weinhold//! Returns the BDirectory's file descriptor.
856338b8dc3SIngo Weinhold/*!	To be used instead of accessing the BDirectory's private \c fDirFd member
857338b8dc3SIngo Weinhold	directly.
858338b8dc3SIngo Weinhold	\return the file descriptor, or -1, if not properly initialized.
859338b8dc3SIngo Weinhold*/
860338b8dc3SIngo Weinholdint
861338b8dc3SIngo WeinholdBDirectory::get_fd() const
862338b8dc3SIngo Weinhold{
863338b8dc3SIngo Weinhold	return fDirFd;
864338b8dc3SIngo Weinhold}
865338b8dc3SIngo Weinhold
866338b8dc3SIngo Weinholdstatus_t
867338b8dc3SIngo WeinholdBDirectory::set_dir_fd(int fd)
868338b8dc3SIngo Weinhold{
869338b8dc3SIngo Weinhold	if (fd < 0)
870338b8dc3SIngo Weinhold		return fd;
871338b8dc3SIngo Weinhold
872338b8dc3SIngo Weinhold	fDirFd = fd;
873338b8dc3SIngo Weinhold
874338b8dc3SIngo Weinhold	status_t error = GetNodeRef(&fDirNodeRef);
875338b8dc3SIngo Weinhold	if (error != B_OK)
876338b8dc3SIngo Weinhold		close_fd();
877338b8dc3SIngo Weinhold
878338b8dc3SIngo Weinhold	return error;
879338b8dc3SIngo Weinhold}
880338b8dc3SIngo Weinhold
881338b8dc3SIngo Weinhold
882338b8dc3SIngo Weinhold
883338b8dc3SIngo Weinhold// C functions
884338b8dc3SIngo Weinhold
885338b8dc3SIngo Weinhold// create_directory
886338b8dc3SIngo Weinhold//! Creates all missing directories along a given path.
887338b8dc3SIngo Weinhold/*!	\param path the directory path name.
888338b8dc3SIngo Weinhold	\param mode a permission specification, which shall be used for the
889338b8dc3SIngo Weinhold		   newly created directories.
890338b8dc3SIngo Weinhold	\return
891338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
892338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a path.
893338b8dc3SIngo Weinhold	- \c B_ENTRY_NOT_FOUND: \a path does not refer to a possible entry.
894338b8dc3SIngo Weinhold	- \c B_PERMISSION_DENIED: Directory permissions didn't allow operation.
895338b8dc3SIngo Weinhold	- \c B_NO_MEMORY: Insufficient memory for operation.
896338b8dc3SIngo Weinhold	- \c B_LINK_LIMIT: Indicates a cyclic loop within the file system.
897338b8dc3SIngo Weinhold	- \c B_BUSY: A node was busy.
898338b8dc3SIngo Weinhold	- \c B_FILE_ERROR: A general file error.
899338b8dc3SIngo Weinhold	- \c B_NOT_A_DIRECTORY: An entry other than a directory with that name does
900338b8dc3SIngo Weinhold	  already exist.
901338b8dc3SIngo Weinhold	- \c B_NO_MORE_FDS: The application has run out of file descriptors.
902338b8dc3SIngo Weinhold	\todo Check for efficency.
903338b8dc3SIngo Weinhold*/
904338b8dc3SIngo Weinholdstatus_t
905338b8dc3SIngo Weinholdcreate_directory(const char *path, mode_t mode)
906338b8dc3SIngo Weinhold{
907338b8dc3SIngo Weinhold	if (!path)
908338b8dc3SIngo Weinhold		return B_BAD_VALUE;
909338b8dc3SIngo Weinhold	// That's the strategy: We start with the first component of the supplied
910338b8dc3SIngo Weinhold	// path, create a BPath object from it and successively add the following
911338b8dc3SIngo Weinhold	// components. Each time we get a new path, we check, if the entry it
912338b8dc3SIngo Weinhold	// refers to exists and is a directory. If it doesn't exist, we try
913338b8dc3SIngo Weinhold	// to create it. This goes on, until we're done with the input path or
914338b8dc3SIngo Weinhold	// an error occurs.
915338b8dc3SIngo Weinhold	BPath dirPath;
916338b8dc3SIngo Weinhold	char *component;
917338b8dc3SIngo Weinhold	int32 nextComponent;
918338b8dc3SIngo Weinhold	do {
919338b8dc3SIngo Weinhold		// get the next path component
920338b8dc3SIngo Weinhold		status_t error = BPrivate::Storage::parse_first_path_component(path,
921338b8dc3SIngo Weinhold			component, nextComponent);
922338b8dc3SIngo Weinhold		if (error != B_OK)
923338b8dc3SIngo Weinhold			return error;
924338b8dc3SIngo Weinhold		// append it to the BPath
925338b8dc3SIngo Weinhold		if (dirPath.InitCheck() == B_NO_INIT)	// first component
926338b8dc3SIngo Weinhold			error = dirPath.SetTo(component);
927338b8dc3SIngo Weinhold		else
928338b8dc3SIngo Weinhold			error = dirPath.Append(component);
929338b8dc3SIngo Weinhold		delete[] component;
930338b8dc3SIngo Weinhold		if (error != B_OK)
931338b8dc3SIngo Weinhold			return error;
932338b8dc3SIngo Weinhold		path += nextComponent;
933338b8dc3SIngo Weinhold		// create a BEntry from the BPath
934338b8dc3SIngo Weinhold		BEntry entry;
935338b8dc3SIngo Weinhold		error = entry.SetTo(dirPath.Path(), true);
936338b8dc3SIngo Weinhold		if (error != B_OK)
937338b8dc3SIngo Weinhold			return error;
938338b8dc3SIngo Weinhold		// check, if it exists
939338b8dc3SIngo Weinhold		if (entry.Exists()) {
940338b8dc3SIngo Weinhold			// yep, it exists
941338b8dc3SIngo Weinhold			if (!entry.IsDirectory())	// but is no directory
942338b8dc3SIngo Weinhold				return B_NOT_A_DIRECTORY;
943338b8dc3SIngo Weinhold		} else {
944338b8dc3SIngo Weinhold			// it doesn't exist -- create it
945338b8dc3SIngo Weinhold			error = _kern_create_dir(-1, dirPath.Path(), mode);
946338b8dc3SIngo Weinhold			if (error != B_OK)
947338b8dc3SIngo Weinhold				return error;
948338b8dc3SIngo Weinhold		}
949338b8dc3SIngo Weinhold	} while (nextComponent != 0);
950338b8dc3SIngo Weinhold	return B_OK;
951338b8dc3SIngo Weinhold}
952338b8dc3SIngo Weinhold
953338b8dc3SIngo Weinhold
954338b8dc3SIngo Weinhold#ifdef USE_OPENBEOS_NAMESPACE
955338b8dc3SIngo Weinhold};		// namespace OpenBeOS
956338b8dc3SIngo Weinhold#endif
957338b8dc3SIngo Weinhold
958