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