13e54c13aSAxel Dörfler /* 2872c3d3fSAxel Dörfler * Copyright 2002-2008, 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 143e54c13aSAxel Dörfler #include <syscalls.h> 1552a38012Sejakowatz 1652a38012Sejakowatz #include <Directory.h> 1752a38012Sejakowatz #include <Entry.h> 1852a38012Sejakowatz #include <File.h> 19b06942c6SIngo Weinhold #include <fs_info.h> 2052a38012Sejakowatz #include <Path.h> 2152a38012Sejakowatz #include <SymLink.h> 22db10640dSIngo Weinhold 233e54c13aSAxel Dörfler #include <fcntl.h> 243e54c13aSAxel Dörfler #include <string.h> 25db10640dSIngo Weinhold 2652a38012Sejakowatz 2743209917SAxel Dörfler extern mode_t __gUmask; 2843209917SAxel Dörfler // declared in sys/umask.c 2943209917SAxel Dörfler 3043209917SAxel Dörfler 3152a38012Sejakowatz //! Creates an uninitialized BDirectory object. 3252a38012Sejakowatz BDirectory::BDirectory() 333e54c13aSAxel Dörfler : 34db10640dSIngo Weinhold fDirFd(-1) 3552a38012Sejakowatz { 3652a38012Sejakowatz } 3752a38012Sejakowatz 3843209917SAxel Dörfler 3943209917SAxel Dörfler /*! \brief Creates a copy of the supplied BDirectory. 4043209917SAxel Dörfler \param dir the BDirectory object to be copied 4152a38012Sejakowatz */ 4252a38012Sejakowatz BDirectory::BDirectory(const BDirectory &dir) 433e54c13aSAxel Dörfler : 44db10640dSIngo Weinhold fDirFd(-1) 4552a38012Sejakowatz { 4652a38012Sejakowatz *this = dir; 4752a38012Sejakowatz } 4852a38012Sejakowatz 4943209917SAxel Dörfler 5052a38012Sejakowatz /*! \brief Creates a BDirectory and initializes it to the directory referred 5152a38012Sejakowatz to by the supplied entry_ref. 5252a38012Sejakowatz \param ref the entry_ref referring to the directory 5352a38012Sejakowatz */ 5452a38012Sejakowatz BDirectory::BDirectory(const entry_ref *ref) 553e54c13aSAxel Dörfler : 56db10640dSIngo Weinhold fDirFd(-1) 5752a38012Sejakowatz { 5852a38012Sejakowatz SetTo(ref); 5952a38012Sejakowatz } 6052a38012Sejakowatz 6143209917SAxel Dörfler 6252a38012Sejakowatz /*! \brief Creates a BDirectory and initializes it to the directory referred 6352a38012Sejakowatz to by the supplied node_ref. 6452a38012Sejakowatz \param nref the node_ref referring to the directory 6552a38012Sejakowatz */ 6652a38012Sejakowatz BDirectory::BDirectory(const node_ref *nref) 673e54c13aSAxel Dörfler : 68db10640dSIngo Weinhold fDirFd(-1) 6952a38012Sejakowatz { 7052a38012Sejakowatz SetTo(nref); 7152a38012Sejakowatz } 7252a38012Sejakowatz 7343209917SAxel Dörfler 7452a38012Sejakowatz /*! \brief Creates a BDirectory and initializes it to the directory referred 7552a38012Sejakowatz to by the supplied BEntry. 7652a38012Sejakowatz \param entry the BEntry referring to the directory 7752a38012Sejakowatz */ 7852a38012Sejakowatz BDirectory::BDirectory(const BEntry *entry) 793e54c13aSAxel Dörfler : 80db10640dSIngo Weinhold fDirFd(-1) 8152a38012Sejakowatz { 8252a38012Sejakowatz SetTo(entry); 8352a38012Sejakowatz } 8452a38012Sejakowatz 8543209917SAxel Dörfler 8652a38012Sejakowatz /*! \brief Creates a BDirectory and initializes it to the directory referred 8752a38012Sejakowatz to by the supplied path name. 8852a38012Sejakowatz \param path the directory's path name 8952a38012Sejakowatz */ 9052a38012Sejakowatz BDirectory::BDirectory(const char *path) 913e54c13aSAxel Dörfler : 92db10640dSIngo Weinhold fDirFd(-1) 9352a38012Sejakowatz { 9452a38012Sejakowatz SetTo(path); 9552a38012Sejakowatz } 9652a38012Sejakowatz 9743209917SAxel Dörfler 9852a38012Sejakowatz /*! \brief Creates a BDirectory and initializes it to the directory referred 9952a38012Sejakowatz to by the supplied path name relative to the specified BDirectory. 10052a38012Sejakowatz \param dir the BDirectory, relative to which the directory's path name is 10152a38012Sejakowatz given 10252a38012Sejakowatz \param path the directory's path name relative to \a dir 10352a38012Sejakowatz */ 10452a38012Sejakowatz BDirectory::BDirectory(const BDirectory *dir, const char *path) 1053e54c13aSAxel Dörfler : 106db10640dSIngo Weinhold fDirFd(-1) 10752a38012Sejakowatz { 10852a38012Sejakowatz SetTo(dir, path); 10952a38012Sejakowatz } 11052a38012Sejakowatz 11143209917SAxel Dörfler 11252a38012Sejakowatz /*! If the BDirectory is properly initialized, the directory's file descriptor 11352a38012Sejakowatz is closed. 11452a38012Sejakowatz */ 11552a38012Sejakowatz BDirectory::~BDirectory() 11652a38012Sejakowatz { 11752a38012Sejakowatz // Also called by the BNode destructor, but we rather try to avoid 11852a38012Sejakowatz // problems with calling virtual functions in the base class destructor. 11952a38012Sejakowatz // Depending on the compiler implementation an object may be degraded to 12052a38012Sejakowatz // an object of the base class after the destructor of the derived class 12152a38012Sejakowatz // has been executed. 12252a38012Sejakowatz close_fd(); 12352a38012Sejakowatz } 12452a38012Sejakowatz 12543209917SAxel Dörfler 12652a38012Sejakowatz /*! \brief Re-initializes the BDirectory to the directory referred to by the 12752a38012Sejakowatz supplied entry_ref. 12852a38012Sejakowatz \param ref the entry_ref referring to the directory 12952a38012Sejakowatz \return 13052a38012Sejakowatz - \c B_OK: Everything went fine. 13152a38012Sejakowatz - \c B_BAD_VALUE: \c NULL \a ref. 13252a38012Sejakowatz - \c B_ENTRY_NOT_FOUND: Directory not found. 13352a38012Sejakowatz - \c B_PERMISSION_DENIED: Directory permissions didn't allow operation. 13452a38012Sejakowatz - \c B_NO_MEMORY: Insufficient memory for operation. 13552a38012Sejakowatz - \c B_LINK_LIMIT: Indicates a cyclic loop within the file system. 13652a38012Sejakowatz - \c B_BUSY: A node was busy. 13752a38012Sejakowatz - \c B_FILE_ERROR: A general file error. 13852a38012Sejakowatz - \c B_NO_MORE_FDS: The application has run out of file descriptors. 13952a38012Sejakowatz */ 14052a38012Sejakowatz status_t 14152a38012Sejakowatz BDirectory::SetTo(const entry_ref *ref) 14252a38012Sejakowatz { 143db10640dSIngo Weinhold // open node 144db10640dSIngo Weinhold status_t error = _SetTo(ref, true); 145db10640dSIngo Weinhold if (error != B_OK) 14652a38012Sejakowatz return error; 147b06942c6SIngo Weinhold 148db10640dSIngo Weinhold // open dir 149db10640dSIngo Weinhold fDirFd = _kern_open_dir_entry_ref(ref->device, ref->directory, ref->name); 150db10640dSIngo Weinhold if (fDirFd < 0) { 151db10640dSIngo Weinhold status_t error = fDirFd; 152db10640dSIngo Weinhold Unset(); 153db10640dSIngo Weinhold return (fCStatus = error); 154db10640dSIngo Weinhold } 155b06942c6SIngo Weinhold 156b06942c6SIngo Weinhold // set close on exec flag on dir FD 157b06942c6SIngo Weinhold fcntl(fDirFd, F_SETFD, FD_CLOEXEC); 158b06942c6SIngo Weinhold 159db10640dSIngo Weinhold return B_OK; 16052a38012Sejakowatz } 16152a38012Sejakowatz 16243209917SAxel Dörfler 16352a38012Sejakowatz /*! \brief Re-initializes the BDirectory to the directory referred to by the 16452a38012Sejakowatz supplied node_ref. 16552a38012Sejakowatz \param nref the node_ref referring to the directory 16652a38012Sejakowatz \return 16752a38012Sejakowatz - \c B_OK: Everything went fine. 16852a38012Sejakowatz - \c B_BAD_VALUE: \c NULL \a nref. 16952a38012Sejakowatz - \c B_ENTRY_NOT_FOUND: Directory not found. 17052a38012Sejakowatz - \c B_PERMISSION_DENIED: Directory permissions didn't allow operation. 17152a38012Sejakowatz - \c B_NO_MEMORY: Insufficient memory for operation. 17252a38012Sejakowatz - \c B_LINK_LIMIT: Indicates a cyclic loop within the file system. 17352a38012Sejakowatz - \c B_BUSY: A node was busy. 17452a38012Sejakowatz - \c B_FILE_ERROR: A general file error. 17552a38012Sejakowatz - \c B_NO_MORE_FDS: The application has run out of file descriptors. 17652a38012Sejakowatz */ 17752a38012Sejakowatz status_t 17852a38012Sejakowatz BDirectory::SetTo(const node_ref *nref) 17952a38012Sejakowatz { 18052a38012Sejakowatz Unset(); 18152a38012Sejakowatz status_t error = (nref ? B_OK : B_BAD_VALUE); 18252a38012Sejakowatz if (error == B_OK) { 18352a38012Sejakowatz entry_ref ref(nref->device, nref->node, "."); 18452a38012Sejakowatz error = SetTo(&ref); 18552a38012Sejakowatz } 18652a38012Sejakowatz set_status(error); 18752a38012Sejakowatz return error; 18852a38012Sejakowatz } 18952a38012Sejakowatz 19043209917SAxel Dörfler 19152a38012Sejakowatz /*! \brief Re-initializes the BDirectory to the directory referred to by the 19252a38012Sejakowatz supplied BEntry. 19352a38012Sejakowatz \param entry the BEntry referring to the directory 19452a38012Sejakowatz \return 19552a38012Sejakowatz - \c B_OK: Everything went fine. 19652a38012Sejakowatz - \c B_BAD_VALUE: \c NULL \a entry. 19752a38012Sejakowatz - \c B_ENTRY_NOT_FOUND: Directory not found. 19852a38012Sejakowatz - \c B_PERMISSION_DENIED: Directory permissions didn't allow operation. 19952a38012Sejakowatz - \c B_NO_MEMORY: Insufficient memory for operation. 20052a38012Sejakowatz - \c B_LINK_LIMIT: Indicates a cyclic loop within the file system. 20152a38012Sejakowatz - \c B_BUSY: A node was busy. 20252a38012Sejakowatz - \c B_FILE_ERROR: A general file error. 20352a38012Sejakowatz - \c B_NO_MORE_FDS: The application has run out of file descriptors. 20452a38012Sejakowatz */ 20552a38012Sejakowatz status_t 20652a38012Sejakowatz BDirectory::SetTo(const BEntry *entry) 20752a38012Sejakowatz { 208db10640dSIngo Weinhold if (!entry) { 20952a38012Sejakowatz Unset(); 210db10640dSIngo Weinhold return (fCStatus = B_BAD_VALUE); 211db10640dSIngo Weinhold } 212b06942c6SIngo Weinhold 213db10640dSIngo Weinhold // open node 214db10640dSIngo Weinhold status_t error = _SetTo(entry->fDirFd, entry->fName, true); 215db10640dSIngo Weinhold if (error != B_OK) 21652a38012Sejakowatz return error; 217b06942c6SIngo Weinhold 218db10640dSIngo Weinhold // open dir 219db10640dSIngo Weinhold fDirFd = _kern_open_dir(entry->fDirFd, entry->fName); 220db10640dSIngo Weinhold if (fDirFd < 0) { 221db10640dSIngo Weinhold status_t error = fDirFd; 222db10640dSIngo Weinhold Unset(); 223db10640dSIngo Weinhold return (fCStatus = error); 224db10640dSIngo Weinhold } 225b06942c6SIngo Weinhold 226b06942c6SIngo Weinhold // set close on exec flag on dir FD 227b06942c6SIngo Weinhold fcntl(fDirFd, F_SETFD, FD_CLOEXEC); 228b06942c6SIngo Weinhold 229db10640dSIngo Weinhold return B_OK; 23052a38012Sejakowatz } 23152a38012Sejakowatz 23243209917SAxel Dörfler 23352a38012Sejakowatz /*! \brief Re-initializes the BDirectory to the directory referred to by the 23452a38012Sejakowatz supplied path name. 23552a38012Sejakowatz \param path the directory's path name 23652a38012Sejakowatz \return 23752a38012Sejakowatz - \c B_OK: Everything went fine. 23852a38012Sejakowatz - \c B_BAD_VALUE: \c NULL \a path. 23952a38012Sejakowatz - \c B_ENTRY_NOT_FOUND: Directory not found. 24052a38012Sejakowatz - \c B_PERMISSION_DENIED: Directory permissions didn't allow operation. 24152a38012Sejakowatz - \c B_NO_MEMORY: Insufficient memory for operation. 24252a38012Sejakowatz - \c B_NAME_TOO_LONG: The supplied path name (\a path) is too long. 24352a38012Sejakowatz - \c B_LINK_LIMIT: Indicates a cyclic loop within the file system. 24452a38012Sejakowatz - \c B_BUSY: A node was busy. 24552a38012Sejakowatz - \c B_FILE_ERROR: A general file error. 24652a38012Sejakowatz - \c B_NO_MORE_FDS: The application has run out of file descriptors. 24752a38012Sejakowatz - \c B_NOT_A_DIRECTORY: \a path includes a non-directory. 24852a38012Sejakowatz */ 24952a38012Sejakowatz status_t 25052a38012Sejakowatz BDirectory::SetTo(const char *path) 25152a38012Sejakowatz { 252db10640dSIngo Weinhold // open node 253db10640dSIngo Weinhold status_t error = _SetTo(-1, path, true); 254db10640dSIngo Weinhold if (error != B_OK) 255db10640dSIngo Weinhold return error; 256b06942c6SIngo Weinhold 257db10640dSIngo Weinhold // open dir 258db10640dSIngo Weinhold fDirFd = _kern_open_dir(-1, path); 259db10640dSIngo Weinhold if (fDirFd < 0) { 260db10640dSIngo Weinhold status_t error = fDirFd; 26152a38012Sejakowatz Unset(); 262db10640dSIngo Weinhold return (fCStatus = error); 26352a38012Sejakowatz } 264b06942c6SIngo Weinhold 265b06942c6SIngo Weinhold // set close on exec flag on dir FD 266b06942c6SIngo Weinhold fcntl(fDirFd, F_SETFD, FD_CLOEXEC); 267b06942c6SIngo Weinhold 268db10640dSIngo Weinhold return B_OK; 26952a38012Sejakowatz } 27052a38012Sejakowatz 27143209917SAxel Dörfler 27252a38012Sejakowatz /*! \brief Re-initializes the BDirectory to the directory referred to by the 27352a38012Sejakowatz supplied path name relative to the specified BDirectory. 27452a38012Sejakowatz \param dir the BDirectory, relative to which the directory's path name is 27552a38012Sejakowatz given 27652a38012Sejakowatz \param path the directory's path name relative to \a dir 27752a38012Sejakowatz \return 27852a38012Sejakowatz - \c B_OK: Everything went fine. 27952a38012Sejakowatz - \c B_BAD_VALUE: \c NULL \a dir or \a path, or \a path is absolute. 28052a38012Sejakowatz - \c B_ENTRY_NOT_FOUND: Directory not found. 28152a38012Sejakowatz - \c B_PERMISSION_DENIED: Directory permissions didn't allow operation. 28252a38012Sejakowatz - \c B_NO_MEMORY: Insufficient memory for operation. 28352a38012Sejakowatz - \c B_NAME_TOO_LONG: The supplied path name (\a path) is too long. 28452a38012Sejakowatz - \c B_LINK_LIMIT: Indicates a cyclic loop within the file system. 28552a38012Sejakowatz - \c B_BUSY: A node was busy. 28652a38012Sejakowatz - \c B_FILE_ERROR: A general file error. 28752a38012Sejakowatz - \c B_NO_MORE_FDS: The application has run out of file descriptors. 28852a38012Sejakowatz - \c B_NOT_A_DIRECTORY: \a path includes a non-directory. 28952a38012Sejakowatz */ 29052a38012Sejakowatz status_t 29152a38012Sejakowatz BDirectory::SetTo(const BDirectory *dir, const char *path) 29252a38012Sejakowatz { 293db10640dSIngo Weinhold if (!dir || !path || BPrivate::Storage::is_absolute_path(path)) { 29452a38012Sejakowatz Unset(); 295db10640dSIngo Weinhold return (fCStatus = B_BAD_VALUE); 296db10640dSIngo Weinhold } 297b06942c6SIngo Weinhold 2983e54c13aSAxel Dörfler int dirFD = dir->fDirFd; 2993e54c13aSAxel Dörfler if (dir == this) { 3003e54c13aSAxel Dörfler // prevent that our file descriptor goes away in _SetTo() 3013e54c13aSAxel Dörfler fDirFd = -1; 3023e54c13aSAxel Dörfler } 3033e54c13aSAxel Dörfler 304db10640dSIngo Weinhold // open node 3053e54c13aSAxel Dörfler status_t error = _SetTo(dirFD, path, true); 306db10640dSIngo Weinhold if (error != B_OK) 30752a38012Sejakowatz return error; 308b06942c6SIngo Weinhold 309db10640dSIngo Weinhold // open dir 3103e54c13aSAxel Dörfler fDirFd = _kern_open_dir(dirFD, path); 311db10640dSIngo Weinhold if (fDirFd < 0) { 312db10640dSIngo Weinhold status_t error = fDirFd; 313db10640dSIngo Weinhold Unset(); 314db10640dSIngo Weinhold return (fCStatus = error); 315db10640dSIngo Weinhold } 316b06942c6SIngo Weinhold 3173e54c13aSAxel Dörfler if (dir == this) { 3183e54c13aSAxel Dörfler // cleanup after _SetTo() 3196a8e3decSStephan Aßmus _kern_close(dirFD); 3203e54c13aSAxel Dörfler } 3213e54c13aSAxel Dörfler 322b06942c6SIngo Weinhold // set close on exec flag on dir FD 323b06942c6SIngo Weinhold fcntl(fDirFd, F_SETFD, FD_CLOEXEC); 324b06942c6SIngo Weinhold 325db10640dSIngo Weinhold return B_OK; 32652a38012Sejakowatz } 32752a38012Sejakowatz 32843209917SAxel Dörfler 32943209917SAxel Dörfler /*! \brief Returns a BEntry referring to the directory represented by this object. 33043209917SAxel Dörfler If the initialization of \a entry fails, it is Unset(). 33152a38012Sejakowatz \param entry a pointer to the entry that shall be set to refer to the 33252a38012Sejakowatz directory 33352a38012Sejakowatz \return 33452a38012Sejakowatz - \c B_OK: Everything went fine. 33552a38012Sejakowatz - \c B_BAD_VALUE: \c NULL \a entry. 33652a38012Sejakowatz - \c B_ENTRY_NOT_FOUND: Directory not found. 33752a38012Sejakowatz - \c B_PERMISSION_DENIED: Directory permissions didn't allow operation. 33852a38012Sejakowatz - \c B_NO_MEMORY: Insufficient memory for operation. 33952a38012Sejakowatz - \c B_LINK_LIMIT: Indicates a cyclic loop within the file system. 34052a38012Sejakowatz - \c B_BUSY: A node was busy. 34152a38012Sejakowatz - \c B_FILE_ERROR: A general file error. 34252a38012Sejakowatz - \c B_NO_MORE_FDS: The application has run out of file descriptors. 34352a38012Sejakowatz */ 34452a38012Sejakowatz status_t 34552a38012Sejakowatz BDirectory::GetEntry(BEntry *entry) const 34652a38012Sejakowatz { 347db10640dSIngo Weinhold if (!entry) 348db10640dSIngo Weinhold return B_BAD_VALUE; 349db10640dSIngo Weinhold if (InitCheck() != B_OK) 350db10640dSIngo Weinhold return B_NO_INIT; 351db10640dSIngo Weinhold return entry->SetTo(this, ".", false); 35252a38012Sejakowatz } 35352a38012Sejakowatz 35443209917SAxel Dörfler 35552a38012Sejakowatz /*! \brief Returns whether the directory represented by this BDirectory is a 35652a38012Sejakowatz root directory of a volume. 35752a38012Sejakowatz \return 35852a38012Sejakowatz - \c true, if the BDirectory is properly initialized and represents a 35952a38012Sejakowatz root directory of some volume, 36052a38012Sejakowatz - \c false, otherwise. 36152a38012Sejakowatz */ 36252a38012Sejakowatz bool 36352a38012Sejakowatz BDirectory::IsRootDirectory() const 36452a38012Sejakowatz { 36552a38012Sejakowatz // compare the directory's node ID with the ID of the root node of the FS 36652a38012Sejakowatz bool result = false; 36752a38012Sejakowatz node_ref ref; 36852a38012Sejakowatz fs_info info; 36952a38012Sejakowatz if (GetNodeRef(&ref) == B_OK && fs_stat_dev(ref.device, &info) == 0) 37052a38012Sejakowatz result = (ref.node == info.root); 37152a38012Sejakowatz return result; 37252a38012Sejakowatz } 37352a38012Sejakowatz 37443209917SAxel Dörfler 37552a38012Sejakowatz /*! \brief Finds an entry referred to by a path relative to the directory 37652a38012Sejakowatz represented by this BDirectory. 37752a38012Sejakowatz \a path may be absolute. If the BDirectory is not properly initialized, 37852a38012Sejakowatz the entry is search relative to the current directory. 37952a38012Sejakowatz If the entry couldn't be found, \a entry is Unset(). 38052a38012Sejakowatz \param path the entry's path name. May be relative to this directory or 38152a38012Sejakowatz absolute. 38252a38012Sejakowatz \param entry a pointer to a BEntry to be initialized with the found entry 38352a38012Sejakowatz \param traverse specifies whether to follow it, if the found entry 38452a38012Sejakowatz is a symbolic link. 38552a38012Sejakowatz \return 38652a38012Sejakowatz - \c B_OK: Everything went fine. 38752a38012Sejakowatz - \c B_BAD_VALUE: \c NULL \a path or \a entry. 38852a38012Sejakowatz - \c B_ENTRY_NOT_FOUND: Entry not found. 38952a38012Sejakowatz - \c B_PERMISSION_DENIED: Directory permissions didn't allow operation. 39052a38012Sejakowatz - \c B_NO_MEMORY: Insufficient memory for operation. 39152a38012Sejakowatz - \c B_NAME_TOO_LONG: The supplied path name (\a path) is too long. 39252a38012Sejakowatz - \c B_LINK_LIMIT: Indicates a cyclic loop within the file system. 39352a38012Sejakowatz - \c B_BUSY: A node was busy. 39452a38012Sejakowatz - \c B_FILE_ERROR: A general file error. 39552a38012Sejakowatz - \c B_NO_MORE_FDS: The application has run out of file descriptors. 39652a38012Sejakowatz - \c B_NOT_A_DIRECTORY: \a path includes a non-directory. 39752a38012Sejakowatz \note The functionality of this method differs from the one of 39852a38012Sejakowatz BEntry::SetTo(BDirectory *, const char *, bool) in that the 39952a38012Sejakowatz latter doesn't require the entry to be existent, whereas this 40052a38012Sejakowatz function does. 40152a38012Sejakowatz */ 40252a38012Sejakowatz status_t 40352a38012Sejakowatz BDirectory::FindEntry(const char *path, BEntry *entry, bool traverse) const 40452a38012Sejakowatz { 40552a38012Sejakowatz status_t error = (path && entry ? B_OK : B_BAD_VALUE); 40652a38012Sejakowatz if (entry) 40752a38012Sejakowatz entry->Unset(); 40852a38012Sejakowatz if (error == B_OK) { 40952a38012Sejakowatz // init a potentially abstract entry 41052a38012Sejakowatz if (InitCheck() == B_OK) 41152a38012Sejakowatz error = entry->SetTo(this, path, traverse); 41252a38012Sejakowatz else 41352a38012Sejakowatz error = entry->SetTo(path, traverse); 41452a38012Sejakowatz // fail, if entry is abstract 41552a38012Sejakowatz if (error == B_OK && !entry->Exists()) { 41652a38012Sejakowatz error = B_ENTRY_NOT_FOUND; 41752a38012Sejakowatz entry->Unset(); 41852a38012Sejakowatz } 41952a38012Sejakowatz } 42052a38012Sejakowatz return error; 42152a38012Sejakowatz } 42252a38012Sejakowatz 42343209917SAxel Dörfler 42452a38012Sejakowatz /*! \brief Returns whether this directory or any of its subdirectories 42552a38012Sejakowatz at any level contain the entry referred to by the supplied path name. 42652a38012Sejakowatz Only entries that match the node flavor specified by \a nodeFlags are 42752a38012Sejakowatz considered. 4285abde301SIngo Weinhold If the BDirectory is not properly initialized, the method returns \c false. 4295abde301SIngo Weinhold A non-absolute path is considered relative to the current directory. 4305abde301SIngo Weinhold 4315abde301SIngo Weinhold \note R5's implementation always returns \c true given an absolute path or 4325abde301SIngo Weinhold an unitialized directory. This implementation is not compatible with that 4335abde301SIngo Weinhold behavior. Instead it converts the path into a BEntry and passes it to the 4345abde301SIngo Weinhold other version of Contains(). 4355abde301SIngo Weinhold 43652a38012Sejakowatz \param path the entry's path name. May be relative to this directory or 43752a38012Sejakowatz absolute. 43852a38012Sejakowatz \param nodeFlags Any of the following: 43952a38012Sejakowatz - \c B_FILE_NODE: The entry must be a file. 44052a38012Sejakowatz - \c B_DIRECTORY_NODE: The entry must be a directory. 44152a38012Sejakowatz - \c B_SYMLINK_NODE: The entry must be a symbolic link. 44252a38012Sejakowatz - \c B_ANY_NODE: The entry may be of any kind. 44352a38012Sejakowatz \return 44452a38012Sejakowatz - \c true, if the entry exists, its kind does match \nodeFlags and the 4455abde301SIngo Weinhold BDirectory is properly initialized and does contain the entry at any 4465abde301SIngo Weinhold level, 44752a38012Sejakowatz - \c false, otherwise 44852a38012Sejakowatz */ 44952a38012Sejakowatz bool 45052a38012Sejakowatz BDirectory::Contains(const char *path, int32 nodeFlags) const 45152a38012Sejakowatz { 4525abde301SIngo Weinhold // check initialization and parameters 4535abde301SIngo Weinhold if (InitCheck() != B_OK) 4545abde301SIngo Weinhold return false; 4555abde301SIngo Weinhold if (!path) 4565abde301SIngo Weinhold return true; // mimic R5 behavior 457d8de23cdSAxel Dörfler 4585abde301SIngo Weinhold // turn the path into a BEntry and let the other version do the work 45952a38012Sejakowatz BEntry entry; 4605abde301SIngo Weinhold if (BPrivate::Storage::is_absolute_path(path)) 46152a38012Sejakowatz entry.SetTo(path); 4625abde301SIngo Weinhold else 4635abde301SIngo Weinhold entry.SetTo(this, path); 464d8de23cdSAxel Dörfler 4655abde301SIngo Weinhold return Contains(&entry, nodeFlags); 46652a38012Sejakowatz } 46752a38012Sejakowatz 46843209917SAxel Dörfler 46952a38012Sejakowatz /*! \brief Returns whether this directory or any of its subdirectories 47052a38012Sejakowatz at any level contain the entry referred to by the supplied BEntry. 47152a38012Sejakowatz Only entries that match the node flavor specified by \a nodeFlags are 47252a38012Sejakowatz considered. 47352a38012Sejakowatz \param entry a BEntry referring to the entry 47452a38012Sejakowatz \param nodeFlags Any of the following: 47552a38012Sejakowatz - \c B_FILE_NODE: The entry must be a file. 47652a38012Sejakowatz - \c B_DIRECTORY_NODE: The entry must be a directory. 47752a38012Sejakowatz - \c B_SYMLINK_NODE: The entry must be a symbolic link. 47852a38012Sejakowatz - \c B_ANY_NODE: The entry may be of any kind. 47952a38012Sejakowatz \return 48052a38012Sejakowatz - \c true, if the BDirectory is properly initialized and the entry of the 48152a38012Sejakowatz matching kind could be found, 48252a38012Sejakowatz - \c false, otherwise 48352a38012Sejakowatz */ 48452a38012Sejakowatz bool 48552a38012Sejakowatz BDirectory::Contains(const BEntry *entry, int32 nodeFlags) const 48652a38012Sejakowatz { 48752a38012Sejakowatz // check, if the entry exists at all 488d8de23cdSAxel Dörfler if (entry == NULL || !entry->Exists() || InitCheck() != B_OK) 489d8de23cdSAxel Dörfler return false; 490d8de23cdSAxel Dörfler 491872c3d3fSAxel Dörfler if (nodeFlags != B_ANY_NODE) { 49252a38012Sejakowatz // test the node kind 493872c3d3fSAxel Dörfler bool result = false; 494872c3d3fSAxel Dörfler if ((nodeFlags & B_FILE_NODE) != 0) 49552a38012Sejakowatz result = entry->IsFile(); 496872c3d3fSAxel Dörfler if (!result && (nodeFlags & B_DIRECTORY_NODE) != 0) 49752a38012Sejakowatz result = entry->IsDirectory(); 498872c3d3fSAxel Dörfler if (!result && (nodeFlags & B_SYMLINK_NODE) != 0) 49952a38012Sejakowatz result = entry->IsSymLink(); 500872c3d3fSAxel Dörfler if (!result) 501872c3d3fSAxel Dörfler return false; 50252a38012Sejakowatz } 503d8de23cdSAxel Dörfler 50452a38012Sejakowatz // If the directory is initialized, get the canonical paths of the dir and 50552a38012Sejakowatz // the entry and check, if the latter is a prefix of the first one. 506db10640dSIngo Weinhold BPath dirPath(this, ".", true); 507db10640dSIngo Weinhold BPath entryPath(entry); 508*e84abff2SMichael Lotz if (dirPath.InitCheck() != B_OK || entryPath.InitCheck() != B_OK) 509872c3d3fSAxel Dörfler return false; 510872c3d3fSAxel Dörfler 511872c3d3fSAxel Dörfler return !strncmp(dirPath.Path(), entryPath.Path(), strlen(dirPath.Path())); 51252a38012Sejakowatz } 513d8de23cdSAxel Dörfler 51452a38012Sejakowatz 51552a38012Sejakowatz /*! \brief Returns the stat structure of the entry referred to by the supplied 51652a38012Sejakowatz path name. 51752a38012Sejakowatz \param path the entry's path name. May be relative to this directory or 51852a38012Sejakowatz absolute, or \c NULL to get the directories stat info. 51952a38012Sejakowatz \param st a pointer to the stat structure to be filled in by this function 52052a38012Sejakowatz \return 52152a38012Sejakowatz - \c B_OK: Everything went fine. 52252a38012Sejakowatz - \c B_BAD_VALUE: \c NULL \a st. 52352a38012Sejakowatz - \c B_ENTRY_NOT_FOUND: Entry not found. 52452a38012Sejakowatz - \c B_PERMISSION_DENIED: Directory permissions didn't allow operation. 52552a38012Sejakowatz - \c B_NO_MEMORY: Insufficient memory for operation. 52652a38012Sejakowatz - \c B_NAME_TOO_LONG: The supplied path name (\a path) is too long. 52752a38012Sejakowatz - \c B_LINK_LIMIT: Indicates a cyclic loop within the file system. 52852a38012Sejakowatz - \c B_BUSY: A node was busy. 52952a38012Sejakowatz - \c B_FILE_ERROR: A general file error. 53052a38012Sejakowatz - \c B_NO_MORE_FDS: The application has run out of file descriptors. 53152a38012Sejakowatz - \c B_NOT_A_DIRECTORY: \a path includes a non-directory. 53252a38012Sejakowatz */ 53352a38012Sejakowatz status_t 53452a38012Sejakowatz BDirectory::GetStatFor(const char *path, struct stat *st) const 53552a38012Sejakowatz { 536db10640dSIngo Weinhold if (!st) 537db10640dSIngo Weinhold return B_BAD_VALUE; 538db10640dSIngo Weinhold if (InitCheck() != B_OK) 539db10640dSIngo Weinhold return B_NO_INIT; 54043209917SAxel Dörfler 54143209917SAxel Dörfler if (path != NULL) { 54243209917SAxel Dörfler if (path[0] == '\0') 543db10640dSIngo Weinhold return B_ENTRY_NOT_FOUND; 54443209917SAxel Dörfler return _kern_read_stat(fDirFd, path, false, st, sizeof(struct stat)); 54543209917SAxel Dörfler } 54643209917SAxel Dörfler return GetStat(st); 54752a38012Sejakowatz } 54852a38012Sejakowatz 54943209917SAxel Dörfler 55043209917SAxel Dörfler /*! \brief Returns the BDirectory's next entry as a BEntry. 55143209917SAxel Dörfler Unlike GetNextDirents() this method ignores the entries "." and "..". 55252a38012Sejakowatz \param entry a pointer to a BEntry to be initialized to the found entry 55352a38012Sejakowatz \param traverse specifies whether to follow it, if the found entry 55452a38012Sejakowatz is a symbolic link. 55552a38012Sejakowatz \note The iterator used by this method is the same one used by 55652a38012Sejakowatz GetNextRef(), GetNextDirents(), Rewind() and CountEntries(). 55752a38012Sejakowatz \return 55852a38012Sejakowatz - \c B_OK: Everything went fine. 55952a38012Sejakowatz - \c B_BAD_VALUE: \c NULL \a entry. 56052a38012Sejakowatz - \c B_ENTRY_NOT_FOUND: No more entries found. 56152a38012Sejakowatz - \c B_PERMISSION_DENIED: Directory permissions didn't allow operation. 56252a38012Sejakowatz - \c B_NO_MEMORY: Insufficient memory for operation. 56352a38012Sejakowatz - \c B_LINK_LIMIT: Indicates a cyclic loop within the file system. 56452a38012Sejakowatz - \c B_BUSY: A node was busy. 56552a38012Sejakowatz - \c B_FILE_ERROR: A general file error. 56652a38012Sejakowatz - \c B_NO_MORE_FDS: The application has run out of file descriptors. 56752a38012Sejakowatz */ 56852a38012Sejakowatz status_t 56952a38012Sejakowatz BDirectory::GetNextEntry(BEntry *entry, bool traverse) 57052a38012Sejakowatz { 57152a38012Sejakowatz status_t error = (entry ? B_OK : B_BAD_VALUE); 57252a38012Sejakowatz if (error == B_OK) { 57352a38012Sejakowatz entry_ref ref; 57452a38012Sejakowatz error = GetNextRef(&ref); 57552a38012Sejakowatz if (error == B_OK) 57652a38012Sejakowatz error = entry->SetTo(&ref, traverse); 57752a38012Sejakowatz } 57852a38012Sejakowatz return error; 57952a38012Sejakowatz } 58052a38012Sejakowatz 58143209917SAxel Dörfler 58243209917SAxel Dörfler /*! \brief Returns the BDirectory's next entry as an entry_ref. 58343209917SAxel Dörfler Unlike GetNextDirents() this method ignores the entries "." and "..". 58452a38012Sejakowatz \param ref a pointer to an entry_ref to be filled in with the data of the 58552a38012Sejakowatz found entry 58652a38012Sejakowatz \param traverse specifies whether to follow it, if the found entry 58752a38012Sejakowatz is a symbolic link. 58852a38012Sejakowatz \note The iterator used be this method is the same one used by 58952a38012Sejakowatz GetNextEntry(), GetNextDirents(), Rewind() and CountEntries(). 59052a38012Sejakowatz \return 59152a38012Sejakowatz - \c B_OK: Everything went fine. 59252a38012Sejakowatz - \c B_BAD_VALUE: \c NULL \a ref. 59352a38012Sejakowatz - \c B_ENTRY_NOT_FOUND: No more entries found. 59452a38012Sejakowatz - \c B_PERMISSION_DENIED: Directory permissions didn't allow operation. 59552a38012Sejakowatz - \c B_NO_MEMORY: Insufficient memory for operation. 59652a38012Sejakowatz - \c B_LINK_LIMIT: Indicates a cyclic loop within the file system. 59752a38012Sejakowatz - \c B_BUSY: A node was busy. 59852a38012Sejakowatz - \c B_FILE_ERROR: A general file error. 59952a38012Sejakowatz - \c B_NO_MORE_FDS: The application has run out of file descriptors. 60052a38012Sejakowatz */ 60152a38012Sejakowatz status_t 60252a38012Sejakowatz BDirectory::GetNextRef(entry_ref *ref) 60352a38012Sejakowatz { 60452a38012Sejakowatz status_t error = (ref ? B_OK : B_BAD_VALUE); 60552a38012Sejakowatz if (error == B_OK && InitCheck() != B_OK) 60652a38012Sejakowatz error = B_FILE_ERROR; 60752a38012Sejakowatz if (error == B_OK) { 60809d84e61STyler Dauwalder BPrivate::Storage::LongDirEntry entry; 60952a38012Sejakowatz bool next = true; 61052a38012Sejakowatz while (error == B_OK && next) { 611db10640dSIngo Weinhold if (GetNextDirents(&entry, sizeof(entry), 1) != 1) { 61252a38012Sejakowatz error = B_ENTRY_NOT_FOUND; 613db10640dSIngo Weinhold } else { 61452a38012Sejakowatz next = (!strcmp(entry.d_name, ".") 61552a38012Sejakowatz || !strcmp(entry.d_name, "..")); 61652a38012Sejakowatz } 61752a38012Sejakowatz } 618db10640dSIngo Weinhold if (error == B_OK) { 619db10640dSIngo Weinhold ref->device = entry.d_pdev; 620db10640dSIngo Weinhold ref->directory = entry.d_pino; 621db10640dSIngo Weinhold error = ref->set_name(entry.d_name); 622db10640dSIngo Weinhold } 62352a38012Sejakowatz } 62452a38012Sejakowatz return error; 62552a38012Sejakowatz } 62652a38012Sejakowatz 62743209917SAxel Dörfler 62843209917SAxel Dörfler /*! \brief Returns the BDirectory's next entries as dirent structures. 62943209917SAxel Dörfler Unlike GetNextEntry() and GetNextRef(), this method returns also 63052a38012Sejakowatz the entries "." and "..". 63152a38012Sejakowatz \param buf a pointer to a buffer to be filled with dirent structures of 63252a38012Sejakowatz the found entries 63352a38012Sejakowatz \param count the maximal number of entries to be returned. 63452a38012Sejakowatz \note The iterator used by this method is the same one used by 63552a38012Sejakowatz GetNextEntry(), GetNextRef(), Rewind() and CountEntries(). 63652a38012Sejakowatz \return 63752a38012Sejakowatz - The number of dirent structures stored in the buffer, 0 when there are 63852a38012Sejakowatz no more entries to be returned. 63952a38012Sejakowatz - \c B_BAD_VALUE: \c NULL \a buf. 64052a38012Sejakowatz - \c B_PERMISSION_DENIED: Directory permissions didn't allow operation. 64152a38012Sejakowatz - \c B_NO_MEMORY: Insufficient memory for operation. 64252a38012Sejakowatz - \c B_NAME_TOO_LONG: The entry's name is too long for the buffer. 64352a38012Sejakowatz - \c B_LINK_LIMIT: Indicates a cyclic loop within the file system. 64452a38012Sejakowatz - \c B_BUSY: A node was busy. 64552a38012Sejakowatz - \c B_FILE_ERROR: A general file error. 64652a38012Sejakowatz - \c B_NO_MORE_FDS: The application has run out of file descriptors. 64752a38012Sejakowatz */ 64852a38012Sejakowatz int32 64952a38012Sejakowatz BDirectory::GetNextDirents(dirent *buf, size_t bufSize, int32 count) 65052a38012Sejakowatz { 651db10640dSIngo Weinhold if (!buf) 652db10640dSIngo Weinhold return B_BAD_VALUE; 653db10640dSIngo Weinhold if (InitCheck() != B_OK) 654db10640dSIngo Weinhold return B_FILE_ERROR; 655db10640dSIngo Weinhold return _kern_read_dir(fDirFd, buf, bufSize, count); 65652a38012Sejakowatz } 65752a38012Sejakowatz 65843209917SAxel Dörfler 65943209917SAxel Dörfler /*! \brief Rewinds the directory iterator. 66043209917SAxel Dörfler \return 66152a38012Sejakowatz - \c B_OK: Everything went fine. 66252a38012Sejakowatz - \c B_PERMISSION_DENIED: Directory permissions didn't allow operation. 66352a38012Sejakowatz - \c B_NO_MEMORY: Insufficient memory for operation. 66452a38012Sejakowatz - \c B_LINK_LIMIT: Indicates a cyclic loop within the file system. 66552a38012Sejakowatz - \c B_BUSY: A node was busy. 66652a38012Sejakowatz - \c B_FILE_ERROR: A general file error. 66752a38012Sejakowatz - \c B_NO_MORE_FDS: The application has run out of file descriptors. 66852a38012Sejakowatz \see GetNextEntry(), GetNextRef(), GetNextDirents(), CountEntries() 66952a38012Sejakowatz */ 67052a38012Sejakowatz status_t 67152a38012Sejakowatz BDirectory::Rewind() 67252a38012Sejakowatz { 673db10640dSIngo Weinhold if (InitCheck() != B_OK) 674db10640dSIngo Weinhold return B_FILE_ERROR; 675db10640dSIngo Weinhold return _kern_rewind_dir(fDirFd); 67652a38012Sejakowatz } 67752a38012Sejakowatz 67843209917SAxel Dörfler 67943209917SAxel Dörfler /*! \brief Returns the number of entries in this directory. 68043209917SAxel Dörfler CountEntries() uses the directory iterator also used by GetNextEntry(), 68152a38012Sejakowatz GetNextRef() and GetNextDirents(). It does a Rewind(), iterates through 68252a38012Sejakowatz the entries and Rewind()s again. The entries "." and ".." are not counted. 68352a38012Sejakowatz \return 68452a38012Sejakowatz - the number of entries in the directory (not counting "." and ".."). 68552a38012Sejakowatz - \c B_PERMISSION_DENIED: Directory permissions didn't allow operation. 68652a38012Sejakowatz - \c B_NO_MEMORY: Insufficient memory for operation. 68752a38012Sejakowatz - \c B_LINK_LIMIT: Indicates a cyclic loop within the file system. 68852a38012Sejakowatz - \c B_BUSY: A node was busy. 68952a38012Sejakowatz - \c B_FILE_ERROR: A general file error. 69052a38012Sejakowatz - \c B_NO_MORE_FDS: The application has run out of file descriptors. 69152a38012Sejakowatz \see GetNextEntry(), GetNextRef(), GetNextDirents(), Rewind() 69252a38012Sejakowatz */ 69352a38012Sejakowatz int32 69452a38012Sejakowatz BDirectory::CountEntries() 69552a38012Sejakowatz { 69652a38012Sejakowatz status_t error = Rewind(); 697db10640dSIngo Weinhold if (error != B_OK) 698db10640dSIngo Weinhold return error; 69952a38012Sejakowatz int32 count = 0; 70009d84e61STyler Dauwalder BPrivate::Storage::LongDirEntry entry; 70152a38012Sejakowatz while (error == B_OK) { 702db10640dSIngo Weinhold if (GetNextDirents(&entry, sizeof(entry), 1) != 1) 703db10640dSIngo Weinhold break; 704db10640dSIngo Weinhold if (strcmp(entry.d_name, ".") != 0 && strcmp(entry.d_name, "..") != 0) 70552a38012Sejakowatz count++; 70652a38012Sejakowatz } 70752a38012Sejakowatz Rewind(); 70852a38012Sejakowatz return (error == B_OK ? count : error); 70952a38012Sejakowatz } 71052a38012Sejakowatz 71143209917SAxel Dörfler 71243209917SAxel Dörfler /*! \brief Creates a new directory. 71343209917SAxel Dörfler If an entry with the supplied name does already exist, the method fails. 71452a38012Sejakowatz \param path the new directory's path name. May be relative to this 71552a38012Sejakowatz directory or absolute. 71652a38012Sejakowatz \param dir a pointer to a BDirectory to be initialized to the newly 71752a38012Sejakowatz created directory. May be \c NULL. 71852a38012Sejakowatz \return 71952a38012Sejakowatz - \c B_OK: Everything went fine. 72052a38012Sejakowatz - \c B_BAD_VALUE: \c NULL \a path. 72152a38012Sejakowatz - \c B_ENTRY_NOT_FOUND: \a path does not refer to a possible entry. 72252a38012Sejakowatz - \c B_PERMISSION_DENIED: Directory permissions didn't allow operation. 72352a38012Sejakowatz - \c B_NO_MEMORY: Insufficient memory for operation. 72452a38012Sejakowatz - \c B_LINK_LIMIT: Indicates a cyclic loop within the file system. 72552a38012Sejakowatz - \c B_BUSY: A node was busy. 72652a38012Sejakowatz - \c B_FILE_ERROR: A general file error. 72752a38012Sejakowatz - \c B_FILE_EXISTS: An entry with that name does already exist. 72852a38012Sejakowatz - \c B_NO_MORE_FDS: The application has run out of file descriptors. 72952a38012Sejakowatz */ 73052a38012Sejakowatz status_t 73152a38012Sejakowatz BDirectory::CreateDirectory(const char *path, BDirectory *dir) 73252a38012Sejakowatz { 733db10640dSIngo Weinhold if (!path) 734db10640dSIngo Weinhold return B_BAD_VALUE; 73543209917SAxel Dörfler 736db10640dSIngo Weinhold // create the dir 737db10640dSIngo Weinhold status_t error = _kern_create_dir(fDirFd, path, 73843209917SAxel Dörfler (S_IRWXU | S_IRWXG | S_IRWXO) & ~__gUmask); 739db10640dSIngo Weinhold if (error != B_OK) 74052a38012Sejakowatz return error; 74143209917SAxel Dörfler 74243209917SAxel Dörfler if (dir == NULL) 743db10640dSIngo Weinhold return B_OK; 74443209917SAxel Dörfler 745db10640dSIngo Weinhold // init the supplied BDirectory 746db10640dSIngo Weinhold if (InitCheck() != B_OK || BPrivate::Storage::is_absolute_path(path)) 747db10640dSIngo Weinhold return dir->SetTo(path); 74843209917SAxel Dörfler 749db10640dSIngo Weinhold return dir->SetTo(this, path); 75052a38012Sejakowatz } 75152a38012Sejakowatz 75243209917SAxel Dörfler 75343209917SAxel Dörfler /*! \brief Creates a new file. 75443209917SAxel Dörfler If a file with the supplied name does already exist, the method fails, 75552a38012Sejakowatz unless it is passed \c false to \a failIfExists -- in that case the file 75652a38012Sejakowatz is truncated to zero size. The new BFile will operate in \c B_READ_WRITE 75752a38012Sejakowatz mode. 75852a38012Sejakowatz \param path the new file's path name. May be relative to this 75952a38012Sejakowatz directory or absolute. 76052a38012Sejakowatz \param file a pointer to a BFile to be initialized to the newly 76152a38012Sejakowatz created file. May be \c NULL. 76252a38012Sejakowatz \param failIfExists \c true, if the method should fail when the file 76352a38012Sejakowatz already exists, \c false otherwise 76452a38012Sejakowatz \return 76552a38012Sejakowatz - \c B_OK: Everything went fine. 76652a38012Sejakowatz - \c B_BAD_VALUE: \c NULL \a path. 76752a38012Sejakowatz - \c B_ENTRY_NOT_FOUND: \a path does not refer to a possible entry. 76852a38012Sejakowatz - \c B_PERMISSION_DENIED: Directory permissions didn't allow operation. 76952a38012Sejakowatz - \c B_NO_MEMORY: Insufficient memory for operation. 77052a38012Sejakowatz - \c B_LINK_LIMIT: Indicates a cyclic loop within the file system. 77152a38012Sejakowatz - \c B_BUSY: A node was busy. 77252a38012Sejakowatz - \c B_FILE_ERROR: A general file error. 77352a38012Sejakowatz - \c B_FILE_EXISTS: A file with that name does already exist and 77452a38012Sejakowatz \c true has been passed for \a failIfExists. 77552a38012Sejakowatz - \c B_IS_A_DIRECTORY: A directory with the supplied name does already 77652a38012Sejakowatz exist. 77752a38012Sejakowatz - \c B_NO_MORE_FDS: The application has run out of file descriptors. 77852a38012Sejakowatz */ 77952a38012Sejakowatz status_t 78052a38012Sejakowatz BDirectory::CreateFile(const char *path, BFile *file, bool failIfExists) 78152a38012Sejakowatz { 782db10640dSIngo Weinhold if (!path) 783db10640dSIngo Weinhold return B_BAD_VALUE; 78452a38012Sejakowatz // Let BFile do the dirty job. 7852586d10eSIngo Weinhold uint32 openMode = B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE 78652a38012Sejakowatz | (failIfExists ? B_FAIL_IF_EXISTS : 0); 78752a38012Sejakowatz BFile tmpFile; 78843209917SAxel Dörfler BFile *realFile = file ? file : &tmpFile; 789db10640dSIngo Weinhold status_t error = B_OK; 79009d84e61STyler Dauwalder if (InitCheck() == B_OK && !BPrivate::Storage::is_absolute_path(path)) 79152a38012Sejakowatz error = realFile->SetTo(this, path, openMode); 79252a38012Sejakowatz else 79352a38012Sejakowatz error = realFile->SetTo(path, openMode); 794db10640dSIngo Weinhold if (error != B_OK && file) // mimic R5 behavior 795db10640dSIngo Weinhold file->Unset(); 79652a38012Sejakowatz return error; 79752a38012Sejakowatz } 79852a38012Sejakowatz 79943209917SAxel Dörfler 80043209917SAxel Dörfler /*! \brief Creates a new symbolic link. 80143209917SAxel Dörfler If an entry with the supplied name does already exist, the method fails. 80252a38012Sejakowatz \param path the new symbolic link's path name. May be relative to this 80352a38012Sejakowatz directory or absolute. 80452a38012Sejakowatz \param linkToPath the path the symbolic link shall point to. 80552a38012Sejakowatz \param dir a pointer to a BSymLink to be initialized to the newly 80652a38012Sejakowatz created symbolic link. May be \c NULL. 80752a38012Sejakowatz \return 80852a38012Sejakowatz - \c B_OK: Everything went fine. 80952a38012Sejakowatz - \c B_BAD_VALUE: \c NULL \a path or \a linkToPath. 81052a38012Sejakowatz - \c B_ENTRY_NOT_FOUND: \a path does not refer to a possible entry. 81152a38012Sejakowatz - \c B_PERMISSION_DENIED: Directory permissions didn't allow operation. 81252a38012Sejakowatz - \c B_NO_MEMORY: Insufficient memory for operation. 81352a38012Sejakowatz - \c B_LINK_LIMIT: Indicates a cyclic loop within the file system. 81452a38012Sejakowatz - \c B_BUSY: A node was busy. 81552a38012Sejakowatz - \c B_FILE_ERROR: A general file error. 81652a38012Sejakowatz - \c B_FILE_EXISTS: An entry with that name does already exist. 81752a38012Sejakowatz - \c B_NO_MORE_FDS: The application has run out of file descriptors. 81852a38012Sejakowatz */ 81952a38012Sejakowatz status_t 82052a38012Sejakowatz BDirectory::CreateSymLink(const char *path, const char *linkToPath, 82152a38012Sejakowatz BSymLink *link) 82252a38012Sejakowatz { 823db10640dSIngo Weinhold if (!path || !linkToPath) 824db10640dSIngo Weinhold return B_BAD_VALUE; 82543209917SAxel Dörfler 826db10640dSIngo Weinhold // create the symlink 827db10640dSIngo Weinhold status_t error = _kern_create_symlink(fDirFd, path, linkToPath, 82843209917SAxel Dörfler (S_IRWXU | S_IRWXG | S_IRWXO) & ~__gUmask); 829db10640dSIngo Weinhold if (error != B_OK) 83052a38012Sejakowatz return error; 83143209917SAxel Dörfler 83243209917SAxel Dörfler if (link == NULL) 833db10640dSIngo Weinhold return B_OK; 83443209917SAxel Dörfler 835db10640dSIngo Weinhold // init the supplied BSymLink 836db10640dSIngo Weinhold if (InitCheck() != B_OK || BPrivate::Storage::is_absolute_path(path)) 837db10640dSIngo Weinhold return link->SetTo(path); 83843209917SAxel Dörfler 839db10640dSIngo Weinhold return link->SetTo(this, path); 84052a38012Sejakowatz } 84152a38012Sejakowatz 84243209917SAxel Dörfler 84343209917SAxel Dörfler /*! \brief Assigns another BDirectory to this BDirectory. 84443209917SAxel Dörfler If the other BDirectory is uninitialized, this one wi'll be too. Otherwise 84552a38012Sejakowatz it will refer to the same directory, unless an error occurs. 84652a38012Sejakowatz \param dir the original BDirectory 84752a38012Sejakowatz \return a reference to this BDirectory 84852a38012Sejakowatz */ 84952a38012Sejakowatz BDirectory & 85052a38012Sejakowatz BDirectory::operator=(const BDirectory &dir) 85152a38012Sejakowatz { 85252a38012Sejakowatz if (&dir != this) { // no need to assign us to ourselves 85352a38012Sejakowatz Unset(); 854db10640dSIngo Weinhold if (dir.InitCheck() == B_OK) 855db10640dSIngo Weinhold SetTo(&dir, "."); 85652a38012Sejakowatz } 85752a38012Sejakowatz return *this; 85852a38012Sejakowatz } 85952a38012Sejakowatz 86052a38012Sejakowatz 86152a38012Sejakowatz // FBC 8627c44680aSIngo Weinhold void BDirectory::_ErectorDirectory1() {} 8637c44680aSIngo Weinhold void BDirectory::_ErectorDirectory2() {} 8647c44680aSIngo Weinhold void BDirectory::_ErectorDirectory3() {} 8657c44680aSIngo Weinhold void BDirectory::_ErectorDirectory4() {} 8667c44680aSIngo Weinhold void BDirectory::_ErectorDirectory5() {} 8677c44680aSIngo Weinhold void BDirectory::_ErectorDirectory6() {} 86852a38012Sejakowatz 86943209917SAxel Dörfler 87052a38012Sejakowatz //! Closes the BDirectory's file descriptor. 87152a38012Sejakowatz void 87252a38012Sejakowatz BDirectory::close_fd() 87352a38012Sejakowatz { 874db10640dSIngo Weinhold if (fDirFd >= 0) { 875db10640dSIngo Weinhold _kern_close(fDirFd); 876db10640dSIngo Weinhold fDirFd = -1; 87752a38012Sejakowatz } 87852a38012Sejakowatz BNode::close_fd(); 87952a38012Sejakowatz } 88052a38012Sejakowatz 88143209917SAxel Dörfler 88243209917SAxel Dörfler /*! \brief Returns the BDirectory's file descriptor. 88343209917SAxel Dörfler To be used instead of accessing the BDirectory's private \c fDirFd member 88452a38012Sejakowatz directly. 88552a38012Sejakowatz \return the file descriptor, or -1, if not properly initialized. 88652a38012Sejakowatz */ 887db10640dSIngo Weinhold int 88852a38012Sejakowatz BDirectory::get_fd() const 88952a38012Sejakowatz { 89052a38012Sejakowatz return fDirFd; 89152a38012Sejakowatz } 89252a38012Sejakowatz 89352a38012Sejakowatz 89443209917SAxel Dörfler // #pragma mark - C functions 89552a38012Sejakowatz 89643209917SAxel Dörfler 89743209917SAxel Dörfler /*! \brief Creates all missing directories along a given path. 89843209917SAxel Dörfler \param path the directory path name. 89952a38012Sejakowatz \param mode a permission specification, which shall be used for the 90052a38012Sejakowatz newly created directories. 90152a38012Sejakowatz \return 90252a38012Sejakowatz - \c B_OK: Everything went fine. 90352a38012Sejakowatz - \c B_BAD_VALUE: \c NULL \a path. 90452a38012Sejakowatz - \c B_ENTRY_NOT_FOUND: \a path does not refer to a possible entry. 90552a38012Sejakowatz - \c B_PERMISSION_DENIED: Directory permissions didn't allow operation. 90652a38012Sejakowatz - \c B_NO_MEMORY: Insufficient memory for operation. 90752a38012Sejakowatz - \c B_LINK_LIMIT: Indicates a cyclic loop within the file system. 90852a38012Sejakowatz - \c B_BUSY: A node was busy. 90952a38012Sejakowatz - \c B_FILE_ERROR: A general file error. 91052a38012Sejakowatz - \c B_NOT_A_DIRECTORY: An entry other than a directory with that name does 91152a38012Sejakowatz already exist. 91252a38012Sejakowatz - \c B_NO_MORE_FDS: The application has run out of file descriptors. 91352a38012Sejakowatz \todo Check for efficency. 91452a38012Sejakowatz */ 91552a38012Sejakowatz status_t 91652a38012Sejakowatz create_directory(const char *path, mode_t mode) 91752a38012Sejakowatz { 918db10640dSIngo Weinhold if (!path) 919db10640dSIngo Weinhold return B_BAD_VALUE; 92052a38012Sejakowatz // That's the strategy: We start with the first component of the supplied 92152a38012Sejakowatz // path, create a BPath object from it and successively add the following 92252a38012Sejakowatz // components. Each time we get a new path, we check, if the entry it 923db10640dSIngo Weinhold // refers to exists and is a directory. If it doesn't exist, we try 92452a38012Sejakowatz // to create it. This goes on, until we're done with the input path or 92552a38012Sejakowatz // an error occurs. 92652a38012Sejakowatz BPath dirPath; 92752a38012Sejakowatz char *component; 92852a38012Sejakowatz int32 nextComponent; 92952a38012Sejakowatz do { 93052a38012Sejakowatz // get the next path component 931db10640dSIngo Weinhold status_t error = BPrivate::Storage::parse_first_path_component(path, 932db10640dSIngo Weinhold component, nextComponent); 933db10640dSIngo Weinhold if (error != B_OK) 934db10640dSIngo Weinhold return error; 93552a38012Sejakowatz // append it to the BPath 93652a38012Sejakowatz if (dirPath.InitCheck() == B_NO_INIT) // first component 93752a38012Sejakowatz error = dirPath.SetTo(component); 93852a38012Sejakowatz else 93952a38012Sejakowatz error = dirPath.Append(component); 94052a38012Sejakowatz delete[] component; 941db10640dSIngo Weinhold if (error != B_OK) 942db10640dSIngo Weinhold return error; 94352a38012Sejakowatz path += nextComponent; 94452a38012Sejakowatz // create a BEntry from the BPath 94552a38012Sejakowatz BEntry entry; 94652a38012Sejakowatz error = entry.SetTo(dirPath.Path(), true); 947db10640dSIngo Weinhold if (error != B_OK) 948db10640dSIngo Weinhold return error; 94952a38012Sejakowatz // check, if it exists 95052a38012Sejakowatz if (entry.Exists()) { 95152a38012Sejakowatz // yep, it exists 95252a38012Sejakowatz if (!entry.IsDirectory()) // but is no directory 953db10640dSIngo Weinhold return B_NOT_A_DIRECTORY; 954db10640dSIngo Weinhold } else { 955db10640dSIngo Weinhold // it doesn't exist -- create it 956db10640dSIngo Weinhold error = _kern_create_dir(-1, dirPath.Path(), mode); 957db10640dSIngo Weinhold if (error != B_OK) 95852a38012Sejakowatz return error; 95952a38012Sejakowatz } 960db10640dSIngo Weinhold } while (nextComponent != 0); 961db10640dSIngo Weinhold return B_OK; 962db10640dSIngo Weinhold } 96352a38012Sejakowatz 964