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 93e54c13aSAxel Dörfler */ 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 3052a38012SejakowatzBDirectory::BDirectory() 313e54c13aSAxel Dörfler : 323e54c13aSAxel Dörfler fDirFd(-1) 3352a38012Sejakowatz{ 3452a38012Sejakowatz} 3552a38012Sejakowatz 3643209917SAxel Dörfler 37160f2d10SAxel DörflerBDirectory::BDirectory(const BDirectory& dir) 383e54c13aSAxel Dörfler : 393e54c13aSAxel Dörfler fDirFd(-1) 4052a38012Sejakowatz{ 4152a38012Sejakowatz *this = dir; 4252a38012Sejakowatz} 4352a38012Sejakowatz 4443209917SAxel Dörfler 45160f2d10SAxel DörflerBDirectory::BDirectory(const entry_ref* ref) 463e54c13aSAxel Dörfler : 473e54c13aSAxel Dörfler fDirFd(-1) 4852a38012Sejakowatz{ 4952a38012Sejakowatz SetTo(ref); 5052a38012Sejakowatz} 5152a38012Sejakowatz 5243209917SAxel Dörfler 53160f2d10SAxel DörflerBDirectory::BDirectory(const node_ref* nref) 543e54c13aSAxel Dörfler : 553e54c13aSAxel Dörfler fDirFd(-1) 5652a38012Sejakowatz{ 5752a38012Sejakowatz SetTo(nref); 5852a38012Sejakowatz} 5952a38012Sejakowatz 6043209917SAxel Dörfler 61160f2d10SAxel DörflerBDirectory::BDirectory(const BEntry* entry) 623e54c13aSAxel Dörfler : 633e54c13aSAxel Dörfler fDirFd(-1) 6452a38012Sejakowatz{ 6552a38012Sejakowatz SetTo(entry); 6652a38012Sejakowatz} 6752a38012Sejakowatz 6843209917SAxel Dörfler 69160f2d10SAxel DörflerBDirectory::BDirectory(const char* path) 703e54c13aSAxel Dörfler : 713e54c13aSAxel Dörfler fDirFd(-1) 7252a38012Sejakowatz{ 7352a38012Sejakowatz SetTo(path); 7452a38012Sejakowatz} 7552a38012Sejakowatz 7643209917SAxel Dörfler 77160f2d10SAxel DörflerBDirectory::BDirectory(const BDirectory* dir, const char* path) 783e54c13aSAxel Dörfler : 793e54c13aSAxel Dörfler fDirFd(-1) 8052a38012Sejakowatz{ 8152a38012Sejakowatz SetTo(dir, path); 8252a38012Sejakowatz} 8352a38012Sejakowatz 8443209917SAxel Dörfler 8552a38012SejakowatzBDirectory::~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 9652a38012Sejakowatzstatus_t 97160f2d10SAxel DörflerBDirectory::SetTo(const entry_ref* ref) 9852a38012Sejakowatz{ 99db10640dSIngo Weinhold // open node 100db10640dSIngo Weinhold status_t error = _SetTo(ref, true); 101db10640dSIngo Weinhold if (error != B_OK) 102db10640dSIngo Weinhold 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); 11052a38012Sejakowatz } 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 11952a38012Sejakowatzstatus_t 120160f2d10SAxel DörflerBDirectory::SetTo(const node_ref* nref) 12152a38012Sejakowatz{ 122872c3d3fSAxel Dörfler 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 13352a38012Sejakowatzstatus_t 134160f2d10SAxel DörflerBDirectory::SetTo(const BEntry* entry) 13552a38012Sejakowatz{ 136db10640dSIngo Weinhold if (!entry) { 137db10640dSIngo Weinhold 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) 144db10640dSIngo Weinhold 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 16152a38012Sejakowatzstatus_t 162160f2d10SAxel DörflerBDirectory::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; 173db10640dSIngo Weinhold 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 18452a38012Sejakowatzstatus_t 185160f2d10SAxel DörflerBDirectory::SetTo(const BDirectory* dir, const char* path) 18652a38012Sejakowatz{ 187db10640dSIngo Weinhold if (!dir || !path || BPrivate::Storage::is_absolute_path(path)) { 188db10640dSIngo Weinhold 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) 201db10640dSIngo Weinhold 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 22352a38012Sejakowatzstatus_t 224160f2d10SAxel DörflerBDirectory::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 23452a38012Sejakowatzbool 23552a38012SejakowatzBDirectory::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 24752a38012Sejakowatzstatus_t 248160f2d10SAxel DörflerBDirectory::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 253160f2d10SAxel Dörfler entry->Unset(); 254160f2d10SAxel Dörfler 255160f2d10SAxel Dörfler // init a potentially abstract entry 256160f2d10SAxel Dörfler status_t status; 257160f2d10SAxel Dörfler if (InitCheck() == B_OK) 258160f2d10SAxel Dörfler status = entry->SetTo(this, path, traverse); 259160f2d10SAxel Dörfler else 260160f2d10SAxel Dörfler status = entry->SetTo(path, traverse); 261160f2d10SAxel Dörfler 262160f2d10SAxel Dörfler // 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 27252a38012Sejakowatzbool 273160f2d10SAxel DörflerBDirectory::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 2825abde301SIngo Weinhold BEntry entry; 2835abde301SIngo Weinhold if (BPrivate::Storage::is_absolute_path(path)) 2845abde301SIngo Weinhold 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 29252a38012Sejakowatzbool 293160f2d10SAxel DörflerBDirectory::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) { 300872c3d3fSAxel Dörfler // test the node kind 301872c3d3fSAxel Dörfler bool result = false; 302872c3d3fSAxel Dörfler if ((nodeFlags & B_FILE_NODE) != 0) 303d8de23cdSAxel Dörfler result = entry->IsFile(); 304872c3d3fSAxel Dörfler if (!result && (nodeFlags & B_DIRECTORY_NODE) != 0) 305d8de23cdSAxel Dörfler result = entry->IsDirectory(); 306872c3d3fSAxel Dörfler if (!result && (nodeFlags & B_SYMLINK_NODE) != 0) 307d8de23cdSAxel Dörfler 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. 314872c3d3fSAxel Dörfler BPath dirPath(this, ".", true); 315872c3d3fSAxel Dörfler BPath entryPath(entry); 316e84abff2SMichael Lotz if (dirPath.InitCheck() != B_OK || entryPath.InitCheck() != B_OK) 317872c3d3fSAxel Dörfler return false; 318d8de23cdSAxel Dörfler 3196020e8a4SRene Gollent uint32 dirLen = strlen(dirPath.Path()); 320bcfe344cSIngo Weinhold 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} 32952a38012Sejakowatz 330872c3d3fSAxel Dörfler 33152a38012Sejakowatzstatus_t 332160f2d10SAxel DörflerBDirectory::GetNextEntry(BEntry* entry, bool traverse) 33352a38012Sejakowatz{ 334901de869SAugustin Cavalier if (entry == NULL) 335901de869SAugustin Cavalier return B_BAD_VALUE; 336901de869SAugustin Cavalier 337901de869SAugustin Cavalier 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 34752a38012Sejakowatzstatus_t 348160f2d10SAxel DörflerBDirectory::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 355901de869SAugustin Cavalier BPrivate::Storage::LongDirEntry entry; 356901de869SAugustin Cavalier bool next = true; 357901de869SAugustin Cavalier while (next) { 358901de869SAugustin Cavalier if (GetNextDirents(&entry, sizeof(entry), 1) != 1) 359901de869SAugustin Cavalier return B_ENTRY_NOT_FOUND; 360901de869SAugustin Cavalier 361901de869SAugustin Cavalier next = (!strcmp(entry.d_name, ".") 362901de869SAugustin Cavalier || !strcmp(entry.d_name, "..")); 36352a38012Sejakowatz } 364901de869SAugustin Cavalier 365901de869SAugustin Cavalier ref->device = entry.d_pdev; 366901de869SAugustin Cavalier ref->directory = entry.d_pino; 367901de869SAugustin Cavalier return ref->set_name(entry.d_name); 36852a38012Sejakowatz} 36952a38012Sejakowatz 37043209917SAxel Dörfler 37152a38012Sejakowatzint32 372160f2d10SAxel DörflerBDirectory::GetNextDirents(dirent* buf, size_t bufSize, int32 count) 37352a38012Sejakowatz{ 374901de869SAugustin Cavalier if (buf == NULL) 375db10640dSIngo Weinhold return B_BAD_VALUE; 376db10640dSIngo Weinhold if (InitCheck() != B_OK) 377db10640dSIngo Weinhold return B_FILE_ERROR; 378db10640dSIngo Weinhold return _kern_read_dir(fDirFd, buf, bufSize, count); 37952a38012Sejakowatz} 38052a38012Sejakowatz 38143209917SAxel Dörfler 38252a38012Sejakowatzstatus_t 38352a38012SejakowatzBDirectory::Rewind() 38452a38012Sejakowatz{ 385db10640dSIngo Weinhold if (InitCheck() != B_OK) 386db10640dSIngo Weinhold return B_FILE_ERROR; 387db10640dSIngo Weinhold return _kern_rewind_dir(fDirFd); 38852a38012Sejakowatz} 38952a38012Sejakowatz 39043209917SAxel Dörfler 39152a38012Sejakowatzint32 39252a38012SejakowatzBDirectory::CountEntries() 39352a38012Sejakowatz{ 39452a38012Sejakowatz status_t error = Rewind(); 395db10640dSIngo Weinhold if (error != B_OK) 396db10640dSIngo Weinhold return error; 39752a38012Sejakowatz int32 count = 0; 398db10640dSIngo Weinhold BPrivate::Storage::LongDirEntry entry; 399db10640dSIngo Weinhold while (error == B_OK) { 400db10640dSIngo Weinhold if (GetNextDirents(&entry, sizeof(entry), 1) != 1) 401db10640dSIngo Weinhold break; 402db10640dSIngo Weinhold if (strcmp(entry.d_name, ".") != 0 && strcmp(entry.d_name, "..") != 0) 403db10640dSIngo Weinhold count++; 40452a38012Sejakowatz } 40552a38012Sejakowatz Rewind(); 40652a38012Sejakowatz return (error == B_OK ? count : error); 40752a38012Sejakowatz} 40852a38012Sejakowatz 40943209917SAxel Dörfler 41052a38012Sejakowatzstatus_t 411160f2d10SAxel DörflerBDirectory::CreateDirectory(const char* path, BDirectory* dir) 41252a38012Sejakowatz{ 413db10640dSIngo Weinhold if (!path) 414db10640dSIngo Weinhold return B_BAD_VALUE; 41543209917SAxel Dörfler 416db10640dSIngo Weinhold // create the dir 417db10640dSIngo Weinhold status_t error = _kern_create_dir(fDirFd, path, 41843209917SAxel Dörfler (S_IRWXU | S_IRWXG | S_IRWXO) & ~__gUmask); 419db10640dSIngo Weinhold if (error != B_OK) 420db10640dSIngo Weinhold return error; 42143209917SAxel Dörfler 42243209917SAxel Dörfler if (dir == NULL) 423db10640dSIngo Weinhold return B_OK; 42443209917SAxel Dörfler 425db10640dSIngo Weinhold // init the supplied BDirectory 426db10640dSIngo Weinhold if (InitCheck() != B_OK || BPrivate::Storage::is_absolute_path(path)) 427db10640dSIngo Weinhold return dir->SetTo(path); 42843209917SAxel Dörfler 42943209917SAxel Dörfler return dir->SetTo(this, path); 43052a38012Sejakowatz} 43152a38012Sejakowatz 43243209917SAxel Dörfler 43352a38012Sejakowatzstatus_t 434160f2d10SAxel DörflerBDirectory::CreateFile(const char* path, BFile* file, bool failIfExists) 43552a38012Sejakowatz{ 436db10640dSIngo Weinhold if (!path) 437db10640dSIngo Weinhold return B_BAD_VALUE; 438160f2d10SAxel Dörfler 439db10640dSIngo Weinhold // Let BFile do the dirty job. 4402586d10eSIngo Weinhold uint32 openMode = B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE 4412586d10eSIngo Weinhold | (failIfExists ? B_FAIL_IF_EXISTS : 0); 442db10640dSIngo Weinhold BFile tmpFile; 443160f2d10SAxel Dörfler BFile* realFile = file ? file : &tmpFile; 444db10640dSIngo Weinhold status_t error = B_OK; 445db10640dSIngo Weinhold if (InitCheck() == B_OK && !BPrivate::Storage::is_absolute_path(path)) 446db10640dSIngo Weinhold error = realFile->SetTo(this, path, openMode); 447db10640dSIngo Weinhold else 448db10640dSIngo Weinhold error = realFile->SetTo(path, openMode); 449db10640dSIngo Weinhold if (error != B_OK && file) // mimic R5 behavior 450db10640dSIngo Weinhold file->Unset(); 45152a38012Sejakowatz return error; 45252a38012Sejakowatz} 45352a38012Sejakowatz 45443209917SAxel Dörfler 45552a38012Sejakowatzstatus_t 456160f2d10SAxel DörflerBDirectory::CreateSymLink(const char* path, const char* linkToPath, 457160f2d10SAxel Dörfler BSymLink* link) 45852a38012Sejakowatz{ 459db10640dSIngo Weinhold if (!path || !linkToPath) 460db10640dSIngo Weinhold return B_BAD_VALUE; 46143209917SAxel Dörfler 462db10640dSIngo Weinhold // create the symlink 463db10640dSIngo Weinhold status_t error = _kern_create_symlink(fDirFd, path, linkToPath, 46443209917SAxel Dörfler (S_IRWXU | S_IRWXG | S_IRWXO) & ~__gUmask); 465db10640dSIngo Weinhold if (error != B_OK) 466db10640dSIngo Weinhold return error; 46743209917SAxel Dörfler 46843209917SAxel Dörfler if (link == NULL) 469db10640dSIngo Weinhold return B_OK; 47043209917SAxel Dörfler 471db10640dSIngo Weinhold // init the supplied BSymLink 472db10640dSIngo Weinhold if (InitCheck() != B_OK || BPrivate::Storage::is_absolute_path(path)) 473db10640dSIngo Weinhold return link->SetTo(path); 47443209917SAxel Dörfler 47543209917SAxel Dörfler return link->SetTo(this, path); 47652a38012Sejakowatz} 47752a38012Sejakowatz 47843209917SAxel Dörfler 479160f2d10SAxel DörflerBDirectory& 480160f2d10SAxel DörflerBDirectory::operator=(const BDirectory& dir) 48152a38012Sejakowatz{ 48252a38012Sejakowatz if (&dir != this) { // no need to assign us to ourselves 48352a38012Sejakowatz Unset(); 484db10640dSIngo Weinhold if (dir.InitCheck() == B_OK) 485db10640dSIngo Weinhold SetTo(&dir, "."); 48652a38012Sejakowatz } 48752a38012Sejakowatz return *this; 48852a38012Sejakowatz} 48952a38012Sejakowatz 49052a38012Sejakowatz 491bcfe344cSIngo Weinholdstatus_t 492160f2d10SAxel DörflerBDirectory::_GetStatFor(const char* path, struct stat* st) const 493bcfe344cSIngo Weinhold{ 494bcfe344cSIngo Weinhold if (!st) 495bcfe344cSIngo Weinhold return B_BAD_VALUE; 496bcfe344cSIngo Weinhold if (InitCheck() != B_OK) 497bcfe344cSIngo Weinhold return B_NO_INIT; 498bcfe344cSIngo Weinhold 499bcfe344cSIngo Weinhold if (path != NULL) { 500bcfe344cSIngo Weinhold if (path[0] == '\0') 501bcfe344cSIngo Weinhold return B_ENTRY_NOT_FOUND; 502bcfe344cSIngo Weinhold return _kern_read_stat(fDirFd, path, false, st, sizeof(struct stat)); 503bcfe344cSIngo Weinhold } 504bcfe344cSIngo Weinhold return GetStat(st); 505bcfe344cSIngo Weinhold} 506bcfe344cSIngo Weinhold 507bcfe344cSIngo Weinhold 508bcfe344cSIngo Weinholdstatus_t 509160f2d10SAxel DörflerBDirectory::_GetStatFor(const char* path, struct stat_beos* st) const 510bcfe344cSIngo Weinhold{ 511bcfe344cSIngo Weinhold struct stat newStat; 512bcfe344cSIngo Weinhold status_t error = _GetStatFor(path, &newStat); 513bcfe344cSIngo Weinhold if (error != B_OK) 514bcfe344cSIngo Weinhold return error; 515bcfe344cSIngo Weinhold 516bcfe344cSIngo Weinhold convert_to_stat_beos(&newStat, st); 517bcfe344cSIngo Weinhold return B_OK; 518bcfe344cSIngo Weinhold} 519bcfe344cSIngo Weinhold 520bcfe344cSIngo Weinhold 52152a38012Sejakowatz// FBC 5227c44680aSIngo Weinholdvoid BDirectory::_ErectorDirectory1() {} 5237c44680aSIngo Weinholdvoid BDirectory::_ErectorDirectory2() {} 5247c44680aSIngo Weinholdvoid BDirectory::_ErectorDirectory3() {} 5257c44680aSIngo Weinholdvoid BDirectory::_ErectorDirectory4() {} 5267c44680aSIngo Weinholdvoid BDirectory::_ErectorDirectory5() {} 5277c44680aSIngo Weinholdvoid BDirectory::_ErectorDirectory6() {} 52852a38012Sejakowatz 52943209917SAxel Dörfler 53052a38012Sejakowatz//! Closes the BDirectory's file descriptor. 53152a38012Sejakowatzvoid 53252a38012SejakowatzBDirectory::close_fd() 53352a38012Sejakowatz{ 534db10640dSIngo Weinhold if (fDirFd >= 0) { 535db10640dSIngo Weinhold _kern_close(fDirFd); 536db10640dSIngo Weinhold fDirFd = -1; 53752a38012Sejakowatz } 53852a38012Sejakowatz BNode::close_fd(); 53952a38012Sejakowatz} 54052a38012Sejakowatz 54143209917SAxel Dörfler 542db10640dSIngo Weinholdint 54352a38012SejakowatzBDirectory::get_fd() const 54452a38012Sejakowatz{ 54552a38012Sejakowatz return fDirFd; 54652a38012Sejakowatz} 54752a38012Sejakowatz 54852a38012Sejakowatz 54943209917SAxel Dörfler// #pragma mark - C functions 55043209917SAxel Dörfler 55152a38012Sejakowatz 5522ac1eb67SJohn Scipione// TODO: Check this method for efficiency. 55352a38012Sejakowatzstatus_t 554160f2d10SAxel Dörflercreate_directory(const char* path, mode_t mode) 55552a38012Sejakowatz{ 556db10640dSIngo Weinhold if (!path) 557db10640dSIngo Weinhold return B_BAD_VALUE; 558160f2d10SAxel Dörfler 55952a38012Sejakowatz // That's the strategy: We start with the first component of the supplied 56052a38012Sejakowatz // path, create a BPath object from it and successively add the following 56152a38012Sejakowatz // components. Each time we get a new path, we check, if the entry it 562db10640dSIngo Weinhold // refers to exists and is a directory. If it doesn't exist, we try 56352a38012Sejakowatz // to create it. This goes on, until we're done with the input path or 56452a38012Sejakowatz // an error occurs. 565db10640dSIngo Weinhold BPath dirPath; 566160f2d10SAxel Dörfler char* component; 567db10640dSIngo Weinhold int32 nextComponent; 568db10640dSIngo Weinhold do { 569db10640dSIngo Weinhold // get the next path component 570db10640dSIngo Weinhold status_t error = BPrivate::Storage::parse_first_path_component(path, 571db10640dSIngo Weinhold component, nextComponent); 572db10640dSIngo Weinhold if (error != B_OK) 573db10640dSIngo Weinhold return error; 574160f2d10SAxel Dörfler 575db10640dSIngo Weinhold // append it to the BPath 576db10640dSIngo Weinhold if (dirPath.InitCheck() == B_NO_INIT) // first component 577db10640dSIngo Weinhold error = dirPath.SetTo(component); 578db10640dSIngo Weinhold else 579db10640dSIngo Weinhold error = dirPath.Append(component); 580db10640dSIngo Weinhold delete[] component; 581db10640dSIngo Weinhold if (error != B_OK) 582db10640dSIngo Weinhold return error; 583db10640dSIngo Weinhold path += nextComponent; 584160f2d10SAxel Dörfler 585db10640dSIngo Weinhold // create a BEntry from the BPath 586db10640dSIngo Weinhold BEntry entry; 587db10640dSIngo Weinhold error = entry.SetTo(dirPath.Path(), true); 588db10640dSIngo Weinhold if (error != B_OK) 589db10640dSIngo Weinhold return error; 590160f2d10SAxel Dörfler 591db10640dSIngo Weinhold // check, if it exists 592db10640dSIngo Weinhold if (entry.Exists()) { 593db10640dSIngo Weinhold // yep, it exists 594db10640dSIngo Weinhold if (!entry.IsDirectory()) // but is no directory 595db10640dSIngo Weinhold return B_NOT_A_DIRECTORY; 596db10640dSIngo Weinhold } else { 597db10640dSIngo Weinhold // it doesn't exist -- create it 5980bb8521bSAxel Dörfler error = _kern_create_dir(-1, dirPath.Path(), mode & ~__gUmask); 599db10640dSIngo Weinhold if (error != B_OK) 600db10640dSIngo Weinhold return error; 601db10640dSIngo Weinhold } 602db10640dSIngo Weinhold } while (nextComponent != 0); 603db10640dSIngo Weinhold return B_OK; 60452a38012Sejakowatz} 60552a38012Sejakowatz 606bcfe344cSIngo Weinhold 607bcfe344cSIngo Weinhold// #pragma mark - symbol versions 608bcfe344cSIngo Weinhold 609bcfe344cSIngo Weinhold 6102c69b5b6SAxel Dörfler#ifdef HAIKU_TARGET_PLATFORM_LIBBE_TEST 61123f83f8cSStephan Aßmus# if __GNUC__ == 2 // gcc 2 6122c69b5b6SAxel Dörfler 61323f83f8cSStephan Aßmus B_DEFINE_SYMBOL_VERSION("_GetStatFor__C10BDirectoryPCcP4stat", 61423f83f8cSStephan Aßmus "GetStatFor__C10BDirectoryPCcP4stat@@LIBBE_TEST"); 6152c69b5b6SAxel Dörfler 61623f83f8cSStephan Aßmus# else // gcc 4 617bcfe344cSIngo Weinhold 61823f83f8cSStephan Aßmus B_DEFINE_SYMBOL_VERSION("_ZNK10BDirectory11_GetStatForEPKcP4stat", 61923f83f8cSStephan Aßmus "_ZNK10BDirectory10GetStatForEPKcP4stat@@LIBBE_TEST"); 620bcfe344cSIngo Weinhold 62123f83f8cSStephan Aßmus# endif // gcc 4 62223f83f8cSStephan Aßmus#else // !HAIKU_TARGET_PLATFORM_LIBBE_TEST 62323f83f8cSStephan Aßmus# if __GNUC__ == 2 // gcc 2 624bcfe344cSIngo Weinhold 62523f83f8cSStephan Aßmus // BeOS compatible GetStatFor() 62623f83f8cSStephan Aßmus B_DEFINE_SYMBOL_VERSION("_GetStatFor__C10BDirectoryPCcP9stat_beos", 62723f83f8cSStephan Aßmus "GetStatFor__C10BDirectoryPCcP4stat@LIBBE_BASE"); 628bcfe344cSIngo Weinhold 62923f83f8cSStephan Aßmus // Haiku GetStatFor() 63023f83f8cSStephan Aßmus B_DEFINE_SYMBOL_VERSION("_GetStatFor__C10BDirectoryPCcP4stat", 63123f83f8cSStephan Aßmus "GetStatFor__C10BDirectoryPCcP4stat@@LIBBE_1_ALPHA1"); 632bcfe344cSIngo Weinhold 63323f83f8cSStephan Aßmus# else // gcc 4 634bcfe344cSIngo Weinhold 63523f83f8cSStephan Aßmus // BeOS compatible GetStatFor() 63623f83f8cSStephan Aßmus B_DEFINE_SYMBOL_VERSION("_ZNK10BDirectory11_GetStatForEPKcP9stat_beos", 63723f83f8cSStephan Aßmus "_ZNK10BDirectory10GetStatForEPKcP4stat@LIBBE_BASE"); 63823f83f8cSStephan Aßmus 63923f83f8cSStephan Aßmus // Haiku GetStatFor() 64023f83f8cSStephan Aßmus B_DEFINE_SYMBOL_VERSION("_ZNK10BDirectory11_GetStatForEPKcP4stat", 64123f83f8cSStephan Aßmus "_ZNK10BDirectory10GetStatForEPKcP4stat@@LIBBE_1_ALPHA1"); 64223f83f8cSStephan Aßmus 64323f83f8cSStephan Aßmus# endif // gcc 4 64423f83f8cSStephan Aßmus#endif // !HAIKU_TARGET_PLATFORM_LIBBE_TEST 645