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