xref: /haiku/src/kits/storage/Directory.cpp (revision 268f99dd7dc4bd7474a8bd2742d3f1ec1de6752a)
13e54c13aSAxel Dörfler /*
2bcfe344cSIngo Weinhold  * Copyright 2002-2009, Haiku Inc.
33e54c13aSAxel Dörfler  * Distributed under the terms of the MIT License.
43e54c13aSAxel Dörfler  *
53e54c13aSAxel Dörfler  * Authors:
63e54c13aSAxel Dörfler  *		Tyler Dauwalder
73e54c13aSAxel Dörfler  *		Ingo Weinhold, bonefish@users.sf.net
83e54c13aSAxel Dörfler  *		Axel Dörfler, axeld@pinc-software.de
952a38012Sejakowatz  */
1052a38012Sejakowatz 
113e54c13aSAxel Dörfler 
123e54c13aSAxel Dörfler #include "storage_support.h"
133e54c13aSAxel Dörfler 
14bcfe344cSIngo Weinhold #include <fcntl.h>
15bcfe344cSIngo Weinhold #include <string.h>
16bcfe344cSIngo Weinhold 
17bcfe344cSIngo Weinhold #include <compat/sys/stat.h>
1852a38012Sejakowatz 
1952a38012Sejakowatz #include <Directory.h>
2052a38012Sejakowatz #include <Entry.h>
2152a38012Sejakowatz #include <File.h>
22b06942c6SIngo Weinhold #include <fs_info.h>
2352a38012Sejakowatz #include <Path.h>
2452a38012Sejakowatz #include <SymLink.h>
25db10640dSIngo Weinhold 
26bcfe344cSIngo Weinhold #include <syscalls.h>
27160f2d10SAxel Dörfler #include <umask.h>
2843209917SAxel Dörfler 
2943209917SAxel Dörfler 
BDirectory()3052a38012Sejakowatz BDirectory::BDirectory()
313e54c13aSAxel Dörfler 	:
32db10640dSIngo Weinhold 	fDirFd(-1)
3352a38012Sejakowatz {
3452a38012Sejakowatz }
3552a38012Sejakowatz 
3643209917SAxel Dörfler 
BDirectory(const BDirectory & dir)3752a38012Sejakowatz BDirectory::BDirectory(const BDirectory& dir)
383e54c13aSAxel Dörfler 	:
39db10640dSIngo Weinhold 	fDirFd(-1)
4052a38012Sejakowatz {
4152a38012Sejakowatz 	*this = dir;
4252a38012Sejakowatz }
4352a38012Sejakowatz 
4443209917SAxel Dörfler 
BDirectory(const entry_ref * ref)4552a38012Sejakowatz BDirectory::BDirectory(const entry_ref* ref)
463e54c13aSAxel Dörfler 	:
47db10640dSIngo Weinhold 	fDirFd(-1)
4852a38012Sejakowatz {
4952a38012Sejakowatz 	SetTo(ref);
5052a38012Sejakowatz }
5152a38012Sejakowatz 
5243209917SAxel Dörfler 
BDirectory(const node_ref * nref)5352a38012Sejakowatz BDirectory::BDirectory(const node_ref* nref)
543e54c13aSAxel Dörfler 	:
55db10640dSIngo Weinhold 	fDirFd(-1)
5652a38012Sejakowatz {
5752a38012Sejakowatz 	SetTo(nref);
5852a38012Sejakowatz }
5952a38012Sejakowatz 
6043209917SAxel Dörfler 
BDirectory(const BEntry * entry)6152a38012Sejakowatz BDirectory::BDirectory(const BEntry* entry)
623e54c13aSAxel Dörfler 	:
63db10640dSIngo Weinhold 	fDirFd(-1)
6452a38012Sejakowatz {
6552a38012Sejakowatz 	SetTo(entry);
6652a38012Sejakowatz }
6752a38012Sejakowatz 
6843209917SAxel Dörfler 
BDirectory(const char * path)6952a38012Sejakowatz BDirectory::BDirectory(const char* path)
703e54c13aSAxel Dörfler 	:
71db10640dSIngo Weinhold 	fDirFd(-1)
7252a38012Sejakowatz {
7352a38012Sejakowatz 	SetTo(path);
7452a38012Sejakowatz }
7552a38012Sejakowatz 
7643209917SAxel Dörfler 
BDirectory(const BDirectory * dir,const char * path)7752a38012Sejakowatz BDirectory::BDirectory(const BDirectory* dir, const char* path)
783e54c13aSAxel Dörfler 	:
79db10640dSIngo Weinhold 	fDirFd(-1)
8052a38012Sejakowatz {
8152a38012Sejakowatz 	SetTo(dir, path);
8252a38012Sejakowatz }
8352a38012Sejakowatz 
8443209917SAxel Dörfler 
~BDirectory()8552a38012Sejakowatz BDirectory::~BDirectory()
8652a38012Sejakowatz {
8752a38012Sejakowatz 	// Also called by the BNode destructor, but we rather try to avoid
8852a38012Sejakowatz 	// problems with calling virtual functions in the base class destructor.
8952a38012Sejakowatz 	// Depending on the compiler implementation an object may be degraded to
9052a38012Sejakowatz 	// an object of the base class after the destructor of the derived class
9152a38012Sejakowatz 	// has been executed.
9252a38012Sejakowatz 	close_fd();
9352a38012Sejakowatz }
9452a38012Sejakowatz 
9543209917SAxel Dörfler 
9652a38012Sejakowatz status_t
SetTo(const entry_ref * ref)9752a38012Sejakowatz BDirectory::SetTo(const entry_ref* ref)
9852a38012Sejakowatz {
99db10640dSIngo Weinhold 	// open node
100db10640dSIngo Weinhold 	status_t error = _SetTo(ref, true);
101db10640dSIngo Weinhold 	if (error != B_OK)
10252a38012Sejakowatz 		return error;
103b06942c6SIngo Weinhold 
104db10640dSIngo Weinhold 	// open dir
105db10640dSIngo Weinhold 	fDirFd = _kern_open_dir_entry_ref(ref->device, ref->directory, ref->name);
106db10640dSIngo Weinhold 	if (fDirFd < 0) {
107db10640dSIngo Weinhold 		status_t error = fDirFd;
108db10640dSIngo Weinhold 		Unset();
109db10640dSIngo Weinhold 		return (fCStatus = error);
110db10640dSIngo Weinhold 	}
111b06942c6SIngo Weinhold 
112b06942c6SIngo Weinhold 	// set close on exec flag on dir FD
113b06942c6SIngo Weinhold 	fcntl(fDirFd, F_SETFD, FD_CLOEXEC);
114b06942c6SIngo Weinhold 
115db10640dSIngo Weinhold 	return B_OK;
11652a38012Sejakowatz }
11752a38012Sejakowatz 
11843209917SAxel Dörfler 
11952a38012Sejakowatz status_t
SetTo(const node_ref * nref)12052a38012Sejakowatz BDirectory::SetTo(const node_ref* nref)
12152a38012Sejakowatz {
12252a38012Sejakowatz 	Unset();
12352a38012Sejakowatz 	status_t error = (nref ? B_OK : B_BAD_VALUE);
12452a38012Sejakowatz 	if (error == B_OK) {
12552a38012Sejakowatz 		entry_ref ref(nref->device, nref->node, ".");
12652a38012Sejakowatz 		error = SetTo(&ref);
12752a38012Sejakowatz 	}
12852a38012Sejakowatz 	set_status(error);
12952a38012Sejakowatz 	return error;
13052a38012Sejakowatz }
13152a38012Sejakowatz 
13243209917SAxel Dörfler 
13352a38012Sejakowatz status_t
SetTo(const BEntry * entry)13452a38012Sejakowatz BDirectory::SetTo(const BEntry* entry)
13552a38012Sejakowatz {
136db10640dSIngo Weinhold 	if (!entry) {
13752a38012Sejakowatz 		Unset();
138db10640dSIngo Weinhold 		return (fCStatus = B_BAD_VALUE);
139db10640dSIngo Weinhold 	}
140b06942c6SIngo Weinhold 
141db10640dSIngo Weinhold 	// open node
142db10640dSIngo Weinhold 	status_t error = _SetTo(entry->fDirFd, entry->fName, true);
143db10640dSIngo Weinhold 	if (error != B_OK)
14452a38012Sejakowatz 		return error;
145b06942c6SIngo Weinhold 
146db10640dSIngo Weinhold 	// open dir
147db10640dSIngo Weinhold 	fDirFd = _kern_open_dir(entry->fDirFd, entry->fName);
148db10640dSIngo Weinhold 	if (fDirFd < 0) {
149db10640dSIngo Weinhold 		status_t error = fDirFd;
150db10640dSIngo Weinhold 		Unset();
151db10640dSIngo Weinhold 		return (fCStatus = error);
152db10640dSIngo Weinhold 	}
153b06942c6SIngo Weinhold 
154b06942c6SIngo Weinhold 	// set close on exec flag on dir FD
155b06942c6SIngo Weinhold 	fcntl(fDirFd, F_SETFD, FD_CLOEXEC);
156b06942c6SIngo Weinhold 
157db10640dSIngo Weinhold 	return B_OK;
15852a38012Sejakowatz }
15952a38012Sejakowatz 
16043209917SAxel Dörfler 
16152a38012Sejakowatz status_t
SetTo(const char * path)16252a38012Sejakowatz BDirectory::SetTo(const char* path)
16352a38012Sejakowatz {
164db10640dSIngo Weinhold 	// open node
165db10640dSIngo Weinhold 	status_t error = _SetTo(-1, path, true);
166db10640dSIngo Weinhold 	if (error != B_OK)
167db10640dSIngo Weinhold 		return error;
168b06942c6SIngo Weinhold 
169db10640dSIngo Weinhold 	// open dir
170db10640dSIngo Weinhold 	fDirFd = _kern_open_dir(-1, path);
171db10640dSIngo Weinhold 	if (fDirFd < 0) {
172db10640dSIngo Weinhold 		status_t error = fDirFd;
17352a38012Sejakowatz 		Unset();
174db10640dSIngo Weinhold 		return (fCStatus = error);
17552a38012Sejakowatz 	}
176b06942c6SIngo Weinhold 
177b06942c6SIngo Weinhold 	// set close on exec flag on dir FD
178b06942c6SIngo Weinhold 	fcntl(fDirFd, F_SETFD, FD_CLOEXEC);
179b06942c6SIngo Weinhold 
180db10640dSIngo Weinhold 	return B_OK;
18152a38012Sejakowatz }
18252a38012Sejakowatz 
18343209917SAxel Dörfler 
18452a38012Sejakowatz status_t
SetTo(const BDirectory * dir,const char * path)18552a38012Sejakowatz BDirectory::SetTo(const BDirectory* dir, const char* path)
18652a38012Sejakowatz {
187db10640dSIngo Weinhold 	if (!dir || !path || BPrivate::Storage::is_absolute_path(path)) {
18852a38012Sejakowatz 		Unset();
189db10640dSIngo Weinhold 		return (fCStatus = B_BAD_VALUE);
190db10640dSIngo Weinhold 	}
191b06942c6SIngo Weinhold 
1923e54c13aSAxel Dörfler 	int dirFD = dir->fDirFd;
1933e54c13aSAxel Dörfler 	if (dir == this) {
1943e54c13aSAxel Dörfler 		// prevent that our file descriptor goes away in _SetTo()
1953e54c13aSAxel Dörfler 		fDirFd = -1;
1963e54c13aSAxel Dörfler 	}
1973e54c13aSAxel Dörfler 
198db10640dSIngo Weinhold 	// open node
1993e54c13aSAxel Dörfler 	status_t error = _SetTo(dirFD, path, true);
200db10640dSIngo Weinhold 	if (error != B_OK)
20152a38012Sejakowatz 		return error;
202b06942c6SIngo Weinhold 
203db10640dSIngo Weinhold 	// open dir
2043e54c13aSAxel Dörfler 	fDirFd = _kern_open_dir(dirFD, path);
205db10640dSIngo Weinhold 	if (fDirFd < 0) {
206db10640dSIngo Weinhold 		status_t error = fDirFd;
207db10640dSIngo Weinhold 		Unset();
208db10640dSIngo Weinhold 		return (fCStatus = error);
209db10640dSIngo Weinhold 	}
210b06942c6SIngo Weinhold 
2113e54c13aSAxel Dörfler 	if (dir == this) {
2123e54c13aSAxel Dörfler 		// cleanup after _SetTo()
2136a8e3decSStephan Aßmus 		_kern_close(dirFD);
2143e54c13aSAxel Dörfler 	}
2153e54c13aSAxel Dörfler 
216b06942c6SIngo Weinhold 	// set close on exec flag on dir FD
217b06942c6SIngo Weinhold 	fcntl(fDirFd, F_SETFD, FD_CLOEXEC);
218b06942c6SIngo Weinhold 
219db10640dSIngo Weinhold 	return B_OK;
22052a38012Sejakowatz }
22152a38012Sejakowatz 
22243209917SAxel Dörfler 
22352a38012Sejakowatz status_t
GetEntry(BEntry * entry) const22452a38012Sejakowatz BDirectory::GetEntry(BEntry* entry) const
22552a38012Sejakowatz {
226db10640dSIngo Weinhold 	if (!entry)
227db10640dSIngo Weinhold 		return B_BAD_VALUE;
228db10640dSIngo Weinhold 	if (InitCheck() != B_OK)
229db10640dSIngo Weinhold 		return B_NO_INIT;
230db10640dSIngo Weinhold 	return entry->SetTo(this, ".", false);
23152a38012Sejakowatz }
23252a38012Sejakowatz 
23343209917SAxel Dörfler 
23452a38012Sejakowatz bool
IsRootDirectory() const23552a38012Sejakowatz BDirectory::IsRootDirectory() const
23652a38012Sejakowatz {
23752a38012Sejakowatz 	// compare the directory's node ID with the ID of the root node of the FS
23852a38012Sejakowatz 	bool result = false;
23952a38012Sejakowatz 	node_ref ref;
24052a38012Sejakowatz 	fs_info info;
24152a38012Sejakowatz 	if (GetNodeRef(&ref) == B_OK && fs_stat_dev(ref.device, &info) == 0)
24252a38012Sejakowatz 		result = (ref.node == info.root);
24352a38012Sejakowatz 	return result;
24452a38012Sejakowatz }
24552a38012Sejakowatz 
24643209917SAxel Dörfler 
24752a38012Sejakowatz status_t
FindEntry(const char * path,BEntry * entry,bool traverse) const24852a38012Sejakowatz BDirectory::FindEntry(const char* path, BEntry* entry, bool traverse) const
24952a38012Sejakowatz {
250160f2d10SAxel Dörfler 	if (path == NULL || entry == NULL)
251160f2d10SAxel Dörfler 		return B_BAD_VALUE;
252160f2d10SAxel Dörfler 
25352a38012Sejakowatz 	entry->Unset();
254160f2d10SAxel Dörfler 
25552a38012Sejakowatz 	// init a potentially abstract entry
256160f2d10SAxel Dörfler 	status_t status;
25752a38012Sejakowatz 	if (InitCheck() == B_OK)
258160f2d10SAxel Dörfler 		status = entry->SetTo(this, path, traverse);
25952a38012Sejakowatz 	else
260160f2d10SAxel Dörfler 		status = entry->SetTo(path, traverse);
261160f2d10SAxel Dörfler 
26252a38012Sejakowatz 	// fail, if entry is abstract
263160f2d10SAxel Dörfler 	if (status == B_OK && !entry->Exists()) {
264160f2d10SAxel Dörfler 		status = B_ENTRY_NOT_FOUND;
26552a38012Sejakowatz 		entry->Unset();
26652a38012Sejakowatz 	}
267160f2d10SAxel Dörfler 
268160f2d10SAxel Dörfler 	return status;
26952a38012Sejakowatz }
27052a38012Sejakowatz 
27143209917SAxel Dörfler 
27252a38012Sejakowatz bool
Contains(const char * path,int32 nodeFlags) const27352a38012Sejakowatz BDirectory::Contains(const char* path, int32 nodeFlags) const
27452a38012Sejakowatz {
2755abde301SIngo Weinhold 	// check initialization and parameters
2765abde301SIngo Weinhold 	if (InitCheck() != B_OK)
2775abde301SIngo Weinhold 		return false;
2785abde301SIngo Weinhold 	if (!path)
2795abde301SIngo Weinhold 		return true;	// mimic R5 behavior
280d8de23cdSAxel Dörfler 
2815abde301SIngo Weinhold 	// turn the path into a BEntry and let the other version do the work
28252a38012Sejakowatz 	BEntry entry;
2835abde301SIngo Weinhold 	if (BPrivate::Storage::is_absolute_path(path))
28452a38012Sejakowatz 		entry.SetTo(path);
2855abde301SIngo Weinhold 	else
2865abde301SIngo Weinhold 		entry.SetTo(this, path);
287d8de23cdSAxel Dörfler 
2885abde301SIngo Weinhold 	return Contains(&entry, nodeFlags);
28952a38012Sejakowatz }
29052a38012Sejakowatz 
29143209917SAxel Dörfler 
29252a38012Sejakowatz bool
Contains(const BEntry * entry,int32 nodeFlags) const29352a38012Sejakowatz BDirectory::Contains(const BEntry* entry, int32 nodeFlags) const
29452a38012Sejakowatz {
29552a38012Sejakowatz 	// check, if the entry exists at all
296d8de23cdSAxel Dörfler 	if (entry == NULL || !entry->Exists() || InitCheck() != B_OK)
297d8de23cdSAxel Dörfler 		return false;
298d8de23cdSAxel Dörfler 
299872c3d3fSAxel Dörfler 	if (nodeFlags != B_ANY_NODE) {
30052a38012Sejakowatz 		// test the node kind
301872c3d3fSAxel Dörfler 		bool result = false;
302872c3d3fSAxel Dörfler 		if ((nodeFlags & B_FILE_NODE) != 0)
30352a38012Sejakowatz 			result = entry->IsFile();
304872c3d3fSAxel Dörfler 		if (!result && (nodeFlags & B_DIRECTORY_NODE) != 0)
30552a38012Sejakowatz 			result = entry->IsDirectory();
306872c3d3fSAxel Dörfler 		if (!result && (nodeFlags & B_SYMLINK_NODE) != 0)
30752a38012Sejakowatz 			result = entry->IsSymLink();
308872c3d3fSAxel Dörfler 		if (!result)
309872c3d3fSAxel Dörfler 			return false;
31052a38012Sejakowatz 	}
311d8de23cdSAxel Dörfler 
31252a38012Sejakowatz 	// If the directory is initialized, get the canonical paths of the dir and
31352a38012Sejakowatz 	// the entry and check, if the latter is a prefix of the first one.
314db10640dSIngo Weinhold 	BPath dirPath(this, ".", true);
315db10640dSIngo Weinhold 	BPath entryPath(entry);
316e84abff2SMichael Lotz 	if (dirPath.InitCheck() != B_OK || entryPath.InitCheck() != B_OK)
317872c3d3fSAxel Dörfler 		return false;
318872c3d3fSAxel Dörfler 
3196020e8a4SRene Gollent 	uint32 dirLen = strlen(dirPath.Path());
3206020e8a4SRene Gollent 
3216020e8a4SRene Gollent 	if (!strncmp(dirPath.Path(), entryPath.Path(), dirLen)) {
32291da3218SRene Gollent 		// if the paths are identical, return a match to stay consistent with
32391da3218SRene Gollent 		// BeOS behavior.
32491da3218SRene Gollent 		if (entryPath.Path()[dirLen] == '\0' || entryPath.Path()[dirLen] == '/')
3256020e8a4SRene Gollent 			return true;
3266020e8a4SRene Gollent 	}
3276020e8a4SRene Gollent 	return false;
32852a38012Sejakowatz }
329d8de23cdSAxel Dörfler 
33052a38012Sejakowatz 
33152a38012Sejakowatz status_t
GetNextEntry(BEntry * entry,bool traverse)33252a38012Sejakowatz BDirectory::GetNextEntry(BEntry* entry, bool traverse)
33352a38012Sejakowatz {
334901de869SAugustin Cavalier 	if (entry == NULL)
335901de869SAugustin Cavalier 		return B_BAD_VALUE;
336901de869SAugustin Cavalier 
33752a38012Sejakowatz 	entry_ref ref;
338901de869SAugustin Cavalier 	status_t status = GetNextRef(&ref);
339901de869SAugustin Cavalier 	if (status != B_OK) {
34026d14a31SAugustin Cavalier 		entry->Unset();
341901de869SAugustin Cavalier 		return status;
342901de869SAugustin Cavalier 	}
343901de869SAugustin Cavalier 	return entry->SetTo(&ref, traverse);
34452a38012Sejakowatz }
34552a38012Sejakowatz 
34643209917SAxel Dörfler 
34752a38012Sejakowatz status_t
GetNextRef(entry_ref * ref)34852a38012Sejakowatz BDirectory::GetNextRef(entry_ref* ref)
34952a38012Sejakowatz {
350901de869SAugustin Cavalier 	if (ref == NULL)
351901de869SAugustin Cavalier 		return B_BAD_VALUE;
352901de869SAugustin Cavalier 	if (InitCheck() != B_OK)
353901de869SAugustin Cavalier 		return B_FILE_ERROR;
354901de869SAugustin Cavalier 
3558f03af00SAugustin Cavalier 	BPrivate::Storage::LongDirEntry longEntry;
356*2532a287SAugustin Cavalier 	struct dirent* entry = longEntry.dirent();
35752a38012Sejakowatz 	bool next = true;
358901de869SAugustin Cavalier 	while (next) {
3598f03af00SAugustin Cavalier 		if (GetNextDirents(entry, sizeof(longEntry), 1) != 1)
360901de869SAugustin Cavalier 			return B_ENTRY_NOT_FOUND;
361901de869SAugustin Cavalier 
3628f03af00SAugustin Cavalier 		next = (!strcmp(entry->d_name, ".")
3638f03af00SAugustin Cavalier 			|| !strcmp(entry->d_name, ".."));
36452a38012Sejakowatz 	}
365901de869SAugustin Cavalier 
3668f03af00SAugustin Cavalier 	ref->device = entry->d_pdev;
3678f03af00SAugustin Cavalier 	ref->directory = entry->d_pino;
3688f03af00SAugustin Cavalier 	return ref->set_name(entry->d_name);
36952a38012Sejakowatz }
37052a38012Sejakowatz 
37143209917SAxel Dörfler 
37252a38012Sejakowatz int32
GetNextDirents(dirent * buf,size_t bufSize,int32 count)37352a38012Sejakowatz BDirectory::GetNextDirents(dirent* buf, size_t bufSize, int32 count)
37452a38012Sejakowatz {
375901de869SAugustin Cavalier 	if (buf == NULL)
376db10640dSIngo Weinhold 		return B_BAD_VALUE;
377db10640dSIngo Weinhold 	if (InitCheck() != B_OK)
378db10640dSIngo Weinhold 		return B_FILE_ERROR;
379db10640dSIngo Weinhold 	return _kern_read_dir(fDirFd, buf, bufSize, count);
38052a38012Sejakowatz }
38152a38012Sejakowatz 
38243209917SAxel Dörfler 
38352a38012Sejakowatz status_t
Rewind()38452a38012Sejakowatz BDirectory::Rewind()
38552a38012Sejakowatz {
386db10640dSIngo Weinhold 	if (InitCheck() != B_OK)
387db10640dSIngo Weinhold 		return B_FILE_ERROR;
388db10640dSIngo Weinhold 	return _kern_rewind_dir(fDirFd);
38952a38012Sejakowatz }
39052a38012Sejakowatz 
39143209917SAxel Dörfler 
39252a38012Sejakowatz int32
CountEntries()39352a38012Sejakowatz BDirectory::CountEntries()
39452a38012Sejakowatz {
39552a38012Sejakowatz 	status_t error = Rewind();
396db10640dSIngo Weinhold 	if (error != B_OK)
397db10640dSIngo Weinhold 		return error;
39852a38012Sejakowatz 	int32 count = 0;
3998f03af00SAugustin Cavalier 	BPrivate::Storage::LongDirEntry longEntry;
400*2532a287SAugustin Cavalier 	struct dirent* entry = longEntry.dirent();
40152a38012Sejakowatz 	while (error == B_OK) {
4028f03af00SAugustin Cavalier 		if (GetNextDirents(entry, sizeof(longEntry), 1) != 1)
403db10640dSIngo Weinhold 			break;
4048f03af00SAugustin Cavalier 		if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0)
40552a38012Sejakowatz 			count++;
40652a38012Sejakowatz 	}
40752a38012Sejakowatz 	Rewind();
40852a38012Sejakowatz 	return (error == B_OK ? count : error);
40952a38012Sejakowatz }
41052a38012Sejakowatz 
41143209917SAxel Dörfler 
41252a38012Sejakowatz status_t
CreateDirectory(const char * path,BDirectory * dir)41352a38012Sejakowatz BDirectory::CreateDirectory(const char* path, BDirectory* dir)
41452a38012Sejakowatz {
415db10640dSIngo Weinhold 	if (!path)
416db10640dSIngo Weinhold 		return B_BAD_VALUE;
41743209917SAxel Dörfler 
418db10640dSIngo Weinhold 	// create the dir
419db10640dSIngo Weinhold 	status_t error = _kern_create_dir(fDirFd, path,
42043209917SAxel Dörfler 		(S_IRWXU | S_IRWXG | S_IRWXO) & ~__gUmask);
421db10640dSIngo Weinhold 	if (error != B_OK)
42252a38012Sejakowatz 		return error;
42343209917SAxel Dörfler 
42443209917SAxel Dörfler 	if (dir == NULL)
425db10640dSIngo Weinhold 		return B_OK;
42643209917SAxel Dörfler 
427db10640dSIngo Weinhold 	// init the supplied BDirectory
428db10640dSIngo Weinhold 	if (InitCheck() != B_OK || BPrivate::Storage::is_absolute_path(path))
429db10640dSIngo Weinhold 		return dir->SetTo(path);
43043209917SAxel Dörfler 
431db10640dSIngo Weinhold 	return dir->SetTo(this, path);
43252a38012Sejakowatz }
43352a38012Sejakowatz 
43443209917SAxel Dörfler 
43552a38012Sejakowatz status_t
CreateFile(const char * path,BFile * file,bool failIfExists)43652a38012Sejakowatz BDirectory::CreateFile(const char* path, BFile* file, bool failIfExists)
43752a38012Sejakowatz {
438db10640dSIngo Weinhold 	if (!path)
439db10640dSIngo Weinhold 		return B_BAD_VALUE;
440160f2d10SAxel Dörfler 
44152a38012Sejakowatz 	// Let BFile do the dirty job.
4422586d10eSIngo Weinhold 	uint32 openMode = B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE
44352a38012Sejakowatz 		| (failIfExists ? B_FAIL_IF_EXISTS : 0);
44452a38012Sejakowatz 	BFile tmpFile;
44543209917SAxel Dörfler 	BFile* realFile = file ? file : &tmpFile;
446db10640dSIngo Weinhold 	status_t error = B_OK;
44709d84e61STyler Dauwalder 	if (InitCheck() == B_OK && !BPrivate::Storage::is_absolute_path(path))
44852a38012Sejakowatz 		error = realFile->SetTo(this, path, openMode);
44952a38012Sejakowatz 	else
45052a38012Sejakowatz 		error = realFile->SetTo(path, openMode);
451db10640dSIngo Weinhold 	if (error != B_OK && file) // mimic R5 behavior
452db10640dSIngo Weinhold 		file->Unset();
45352a38012Sejakowatz 	return error;
45452a38012Sejakowatz }
45552a38012Sejakowatz 
45643209917SAxel Dörfler 
45752a38012Sejakowatz status_t
CreateSymLink(const char * path,const char * linkToPath,BSymLink * link)45852a38012Sejakowatz BDirectory::CreateSymLink(const char* path, const char* linkToPath,
45952a38012Sejakowatz 	BSymLink* link)
46052a38012Sejakowatz {
461db10640dSIngo Weinhold 	if (!path || !linkToPath)
462db10640dSIngo Weinhold 		return B_BAD_VALUE;
46343209917SAxel Dörfler 
464db10640dSIngo Weinhold 	// create the symlink
465db10640dSIngo Weinhold 	status_t error = _kern_create_symlink(fDirFd, path, linkToPath,
46643209917SAxel Dörfler 		(S_IRWXU | S_IRWXG | S_IRWXO) & ~__gUmask);
467db10640dSIngo Weinhold 	if (error != B_OK)
46852a38012Sejakowatz 		return error;
46943209917SAxel Dörfler 
47043209917SAxel Dörfler 	if (link == NULL)
471db10640dSIngo Weinhold 		return B_OK;
47243209917SAxel Dörfler 
473db10640dSIngo Weinhold 	// init the supplied BSymLink
474db10640dSIngo Weinhold 	if (InitCheck() != B_OK || BPrivate::Storage::is_absolute_path(path))
475db10640dSIngo Weinhold 		return link->SetTo(path);
47643209917SAxel Dörfler 
477db10640dSIngo Weinhold 	return link->SetTo(this, path);
47852a38012Sejakowatz }
47952a38012Sejakowatz 
48043209917SAxel Dörfler 
48152a38012Sejakowatz BDirectory&
operator =(const BDirectory & dir)48252a38012Sejakowatz BDirectory::operator=(const BDirectory& dir)
48352a38012Sejakowatz {
48452a38012Sejakowatz 	if (&dir != this) {	// no need to assign us to ourselves
48552a38012Sejakowatz 		Unset();
486db10640dSIngo Weinhold 		if (dir.InitCheck() == B_OK)
487db10640dSIngo Weinhold 			SetTo(&dir, ".");
48852a38012Sejakowatz 	}
48952a38012Sejakowatz 	return *this;
49052a38012Sejakowatz }
49152a38012Sejakowatz 
49252a38012Sejakowatz 
493bcfe344cSIngo Weinhold status_t
_GetStatFor(const char * path,struct stat * st) const494bcfe344cSIngo Weinhold BDirectory::_GetStatFor(const char* path, struct stat* st) const
495bcfe344cSIngo Weinhold {
496bcfe344cSIngo Weinhold 	if (!st)
497bcfe344cSIngo Weinhold 		return B_BAD_VALUE;
498bcfe344cSIngo Weinhold 	if (InitCheck() != B_OK)
499bcfe344cSIngo Weinhold 		return B_NO_INIT;
500bcfe344cSIngo Weinhold 
501bcfe344cSIngo Weinhold 	if (path != NULL) {
502bcfe344cSIngo Weinhold 		if (path[0] == '\0')
503bcfe344cSIngo Weinhold 			return B_ENTRY_NOT_FOUND;
504bcfe344cSIngo Weinhold 		return _kern_read_stat(fDirFd, path, false, st, sizeof(struct stat));
505bcfe344cSIngo Weinhold 	}
506bcfe344cSIngo Weinhold 	return GetStat(st);
507bcfe344cSIngo Weinhold }
508bcfe344cSIngo Weinhold 
509bcfe344cSIngo Weinhold 
510bcfe344cSIngo Weinhold status_t
_GetStatFor(const char * path,struct stat_beos * st) const511bcfe344cSIngo Weinhold BDirectory::_GetStatFor(const char* path, struct stat_beos* st) const
512bcfe344cSIngo Weinhold {
513bcfe344cSIngo Weinhold 	struct stat newStat;
514bcfe344cSIngo Weinhold 	status_t error = _GetStatFor(path, &newStat);
515bcfe344cSIngo Weinhold 	if (error != B_OK)
516bcfe344cSIngo Weinhold 		return error;
517bcfe344cSIngo Weinhold 
518bcfe344cSIngo Weinhold 	convert_to_stat_beos(&newStat, st);
519bcfe344cSIngo Weinhold 	return B_OK;
520bcfe344cSIngo Weinhold }
521bcfe344cSIngo Weinhold 
522bcfe344cSIngo Weinhold 
52352a38012Sejakowatz // FBC
_ErectorDirectory1()5247c44680aSIngo Weinhold void BDirectory::_ErectorDirectory1() {}
_ErectorDirectory2()5257c44680aSIngo Weinhold void BDirectory::_ErectorDirectory2() {}
_ErectorDirectory3()5267c44680aSIngo Weinhold void BDirectory::_ErectorDirectory3() {}
_ErectorDirectory4()5277c44680aSIngo Weinhold void BDirectory::_ErectorDirectory4() {}
_ErectorDirectory5()5287c44680aSIngo Weinhold void BDirectory::_ErectorDirectory5() {}
_ErectorDirectory6()5297c44680aSIngo Weinhold void BDirectory::_ErectorDirectory6() {}
53052a38012Sejakowatz 
53143209917SAxel Dörfler 
53252a38012Sejakowatz //! Closes the BDirectory's file descriptor.
53352a38012Sejakowatz void
close_fd()53452a38012Sejakowatz BDirectory::close_fd()
53552a38012Sejakowatz {
536db10640dSIngo Weinhold 	if (fDirFd >= 0) {
537db10640dSIngo Weinhold 		_kern_close(fDirFd);
538db10640dSIngo Weinhold 		fDirFd = -1;
53952a38012Sejakowatz 	}
54052a38012Sejakowatz 	BNode::close_fd();
54152a38012Sejakowatz }
54252a38012Sejakowatz 
54343209917SAxel Dörfler 
544db10640dSIngo Weinhold int
get_fd() const54552a38012Sejakowatz BDirectory::get_fd() const
54652a38012Sejakowatz {
54752a38012Sejakowatz 	return fDirFd;
54852a38012Sejakowatz }
54952a38012Sejakowatz 
55052a38012Sejakowatz 
55143209917SAxel Dörfler //	#pragma mark - C functions
55252a38012Sejakowatz 
55343209917SAxel Dörfler 
5542ac1eb67SJohn Scipione // TODO: Check this method for efficiency.
55552a38012Sejakowatz status_t
create_directory(const char * path,mode_t mode)55652a38012Sejakowatz create_directory(const char* path, mode_t mode)
55752a38012Sejakowatz {
558db10640dSIngo Weinhold 	if (!path)
559db10640dSIngo Weinhold 		return B_BAD_VALUE;
560160f2d10SAxel Dörfler 
56152a38012Sejakowatz 	// That's the strategy: We start with the first component of the supplied
56252a38012Sejakowatz 	// path, create a BPath object from it and successively add the following
56352a38012Sejakowatz 	// components. Each time we get a new path, we check, if the entry it
564db10640dSIngo Weinhold 	// refers to exists and is a directory. If it doesn't exist, we try
56552a38012Sejakowatz 	// to create it. This goes on, until we're done with the input path or
56652a38012Sejakowatz 	// an error occurs.
56752a38012Sejakowatz 	BPath dirPath;
56852a38012Sejakowatz 	char* component;
56952a38012Sejakowatz 	int32 nextComponent;
57052a38012Sejakowatz 	do {
57152a38012Sejakowatz 		// get the next path component
572db10640dSIngo Weinhold 		status_t error = BPrivate::Storage::parse_first_path_component(path,
573db10640dSIngo Weinhold 			component, nextComponent);
574db10640dSIngo Weinhold 		if (error != B_OK)
575db10640dSIngo Weinhold 			return error;
576160f2d10SAxel Dörfler 
57752a38012Sejakowatz 		// append it to the BPath
57852a38012Sejakowatz 		if (dirPath.InitCheck() == B_NO_INIT)	// first component
57952a38012Sejakowatz 			error = dirPath.SetTo(component);
58052a38012Sejakowatz 		else
58152a38012Sejakowatz 			error = dirPath.Append(component);
58252a38012Sejakowatz 		delete[] component;
583db10640dSIngo Weinhold 		if (error != B_OK)
584db10640dSIngo Weinhold 			return error;
58552a38012Sejakowatz 		path += nextComponent;
586160f2d10SAxel Dörfler 
58752a38012Sejakowatz 		// create a BEntry from the BPath
58852a38012Sejakowatz 		BEntry entry;
58952a38012Sejakowatz 		error = entry.SetTo(dirPath.Path(), true);
590db10640dSIngo Weinhold 		if (error != B_OK)
591db10640dSIngo Weinhold 			return error;
592160f2d10SAxel Dörfler 
59352a38012Sejakowatz 		// check, if it exists
59452a38012Sejakowatz 		if (entry.Exists()) {
59552a38012Sejakowatz 			// yep, it exists
59652a38012Sejakowatz 			if (!entry.IsDirectory())	// but is no directory
597db10640dSIngo Weinhold 				return B_NOT_A_DIRECTORY;
598db10640dSIngo Weinhold 		} else {
599db10640dSIngo Weinhold 			// it doesn't exist -- create it
6000bb8521bSAxel Dörfler 			error = _kern_create_dir(-1, dirPath.Path(), mode & ~__gUmask);
601db10640dSIngo Weinhold 			if (error != B_OK)
60252a38012Sejakowatz 				return error;
60352a38012Sejakowatz 		}
604db10640dSIngo Weinhold 	} while (nextComponent != 0);
605db10640dSIngo Weinhold 	return B_OK;
606db10640dSIngo Weinhold }
60752a38012Sejakowatz 
608bcfe344cSIngo Weinhold 
609bcfe344cSIngo Weinhold // #pragma mark - symbol versions
610bcfe344cSIngo Weinhold 
611bcfe344cSIngo Weinhold 
6122c69b5b6SAxel Dörfler #ifdef HAIKU_TARGET_PLATFORM_LIBBE_TEST
61323f83f8cSStephan Aßmus #	if __GNUC__ == 2	// gcc 2
6142c69b5b6SAxel Dörfler 
6152c69b5b6SAxel Dörfler 	B_DEFINE_SYMBOL_VERSION("_GetStatFor__C10BDirectoryPCcP4stat",
6162c69b5b6SAxel Dörfler 		"GetStatFor__C10BDirectoryPCcP4stat@@LIBBE_TEST");
6172c69b5b6SAxel Dörfler 
61823f83f8cSStephan Aßmus #	else	// gcc 4
61923f83f8cSStephan Aßmus 
62023f83f8cSStephan Aßmus 	B_DEFINE_SYMBOL_VERSION("_ZNK10BDirectory11_GetStatForEPKcP4stat",
62123f83f8cSStephan Aßmus 		"_ZNK10BDirectory10GetStatForEPKcP4stat@@LIBBE_TEST");
62223f83f8cSStephan Aßmus 
62323f83f8cSStephan Aßmus #	endif	// gcc 4
62423f83f8cSStephan Aßmus #else	// !HAIKU_TARGET_PLATFORM_LIBBE_TEST
62523f83f8cSStephan Aßmus #	if __GNUC__ == 2	// gcc 2
626bcfe344cSIngo Weinhold 
627bcfe344cSIngo Weinhold 	// BeOS compatible GetStatFor()
628bcfe344cSIngo Weinhold 	B_DEFINE_SYMBOL_VERSION("_GetStatFor__C10BDirectoryPCcP9stat_beos",
629bcfe344cSIngo Weinhold 		"GetStatFor__C10BDirectoryPCcP4stat@LIBBE_BASE");
630bcfe344cSIngo Weinhold 
631bcfe344cSIngo Weinhold 	// Haiku GetStatFor()
632bcfe344cSIngo Weinhold 	B_DEFINE_SYMBOL_VERSION("_GetStatFor__C10BDirectoryPCcP4stat",
633bcfe344cSIngo Weinhold 		"GetStatFor__C10BDirectoryPCcP4stat@@LIBBE_1_ALPHA1");
634bcfe344cSIngo Weinhold 
635bcfe344cSIngo Weinhold #	else	// gcc 4
636bcfe344cSIngo Weinhold 
637bcfe344cSIngo Weinhold 	// BeOS compatible GetStatFor()
638bcfe344cSIngo Weinhold 	B_DEFINE_SYMBOL_VERSION("_ZNK10BDirectory11_GetStatForEPKcP9stat_beos",
639bcfe344cSIngo Weinhold 		"_ZNK10BDirectory10GetStatForEPKcP4stat@LIBBE_BASE");
640bcfe344cSIngo Weinhold 
641bcfe344cSIngo Weinhold 	// Haiku GetStatFor()
642bcfe344cSIngo Weinhold 	B_DEFINE_SYMBOL_VERSION("_ZNK10BDirectory11_GetStatForEPKcP4stat",
643bcfe344cSIngo Weinhold 		"_ZNK10BDirectory10GetStatForEPKcP4stat@@LIBBE_1_ALPHA1");
644bcfe344cSIngo Weinhold 
645bcfe344cSIngo Weinhold #	endif	// gcc 4
64623f83f8cSStephan Aßmus #endif	// !HAIKU_TARGET_PLATFORM_LIBBE_TEST
647