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 19 extern Node *get_node_from(int fd); 20 21 22 using std::nothrow; 23 24 25 namespace BFS { 26 27 28 Directory::Directory(Volume &volume, block_run run) 29 : 30 fStream(volume, run), 31 fTree(&fStream) 32 { 33 } 34 35 36 Directory::Directory(Volume &volume, off_t id) 37 : 38 fStream(volume, id), 39 fTree(&fStream) 40 { 41 } 42 43 44 Directory::Directory(const Stream &stream) 45 : 46 fStream(stream), 47 fTree(&fStream) 48 { 49 } 50 51 52 Directory::~Directory() 53 { 54 } 55 56 57 status_t 58 Directory::InitCheck() 59 { 60 return fStream.InitCheck(); 61 } 62 63 64 status_t 65 Directory::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 77 status_t 78 Directory::Close(void *cookie) 79 { 80 _inherited::Close(cookie); 81 82 delete (TreeIterator *)cookie; 83 return B_OK; 84 } 85 86 87 Node* 88 Directory::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 98 status_t 99 Directory::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 109 status_t 110 Directory::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 129 status_t 130 Directory::Rewind(void *cookie) 131 { 132 TreeIterator *iterator = (TreeIterator *)cookie; 133 134 return iterator->Rewind(); 135 } 136 137 138 bool 139 Directory::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 163 status_t 164 Directory::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 175 ino_t 176 Directory::Inode() const 177 { 178 return fStream.ID(); 179 } 180 181 182 } // namespace BFS 183