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