1/* 2 * Copyright 2003-2013, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include "Directory.h" 8#include "File.h" 9#include "Link.h" 10 11#include <StorageDefs.h> 12#include <KernelExport.h> 13 14#include <string.h> 15#include <unistd.h> 16 17 18// temp. private VFS API 19extern Node *get_node_from(int fd); 20 21 22using std::nothrow; 23 24 25namespace BFS { 26 27 28Directory::Directory(Volume &volume, block_run run) 29 : 30 fStream(volume, run), 31 fTree(&fStream) 32{ 33} 34 35 36Directory::Directory(Volume &volume, off_t id) 37 : 38 fStream(volume, id), 39 fTree(&fStream) 40{ 41} 42 43 44Directory::Directory(const Stream &stream) 45 : 46 fStream(stream), 47 fTree(&fStream) 48{ 49} 50 51 52Directory::~Directory() 53{ 54} 55 56 57status_t 58Directory::InitCheck() 59{ 60 return fStream.InitCheck(); 61} 62 63 64status_t 65Directory::Open(void **_cookie, int mode) 66{ 67 _inherited::Open(_cookie, mode); 68 69 *_cookie = (void *)new(nothrow) TreeIterator(&fTree); 70 if (*_cookie == NULL) 71 return B_NO_MEMORY; 72 73 return B_OK; 74} 75 76 77status_t 78Directory::Close(void *cookie) 79{ 80 _inherited::Close(cookie); 81 82 delete (TreeIterator *)cookie; 83 return B_OK; 84} 85 86 87Node* 88Directory::LookupDontTraverse(const char* name) 89{ 90 off_t id; 91 if (fTree.Find((uint8 *)name, strlen(name), &id) < B_OK) 92 return NULL; 93 94 return Stream::NodeFactory(fStream.GetVolume(), id); 95} 96 97 98status_t 99Directory::GetNextEntry(void *cookie, char *name, size_t size) 100{ 101 TreeIterator *iterator = (TreeIterator *)cookie; 102 uint16 length; 103 off_t id; 104 105 return iterator->GetNextEntry(name, &length, size, &id); 106} 107 108 109status_t 110Directory::GetNextNode(void *cookie, Node **_node) 111{ 112 TreeIterator *iterator = (TreeIterator *)cookie; 113 char name[B_FILE_NAME_LENGTH]; 114 uint16 length; 115 off_t id; 116 117 status_t status = iterator->GetNextEntry(name, &length, sizeof(name), &id); 118 if (status != B_OK) 119 return status; 120 121 *_node = Stream::NodeFactory(fStream.GetVolume(), id); 122 if (*_node == NULL) 123 return B_ERROR; 124 125 return B_OK; 126} 127 128 129status_t 130Directory::Rewind(void *cookie) 131{ 132 TreeIterator *iterator = (TreeIterator *)cookie; 133 134 return iterator->Rewind(); 135} 136 137 138bool 139Directory::IsEmpty() 140{ 141 TreeIterator iterator(&fTree); 142 143 // index and attribute directories are really empty when they are 144 // empty - directories for standard files always contain ".", and 145 // "..", so we need to ignore those two 146 147 uint32 count = 0; 148 char name[BPLUSTREE_MAX_KEY_LENGTH]; 149 uint16 length; 150 off_t id; 151 while (iterator.GetNextEntry(name, &length, B_FILE_NAME_LENGTH, &id) 152 == B_OK) { 153 if (fStream.Mode() & (S_ATTR_DIR | S_INDEX_DIR)) 154 return false; 155 156 if (++count > 2 || (strcmp(".", name) && strcmp("..", name))) 157 return false; 158 } 159 return true; 160} 161 162 163status_t 164Directory::GetName(char *name, size_t size) const 165{ 166 if (fStream.inode_num == fStream.GetVolume().Root()) { 167 strlcpy(name, fStream.GetVolume().SuperBlock().name, size); 168 return B_OK; 169 } 170 171 return fStream.GetName(name, size); 172} 173 174 175ino_t 176Directory::Inode() const 177{ 178 return fStream.ID(); 179} 180 181 182} // namespace BFS 183