1 /* 2 ** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 ** Distributed under the terms of the OpenBeOS License. 4 */ 5 6 7 #include "Directory.h" 8 #include "Volume.h" 9 #include "File.h" 10 11 #include <StorageDefs.h> 12 #include <util/kernel_cpp.h> 13 14 #include <string.h> 15 #include <unistd.h> 16 #include <stdio.h> 17 18 19 namespace FFS { 20 21 Directory::Directory(Volume &volume, ::Directory* parent, int32 block) 22 : 23 ::Directory(parent), 24 fVolume(volume) 25 { 26 void *data = malloc(volume.BlockSize()); 27 if (data == NULL) 28 return; 29 30 if (read_pos(volume.Device(), block * volume.BlockSize(), data, volume.BlockSize()) == volume.BlockSize()) 31 fNode.SetTo(data, volume.BlockSize()); 32 } 33 34 35 Directory::Directory(Volume &volume, ::Directory* parent, RootBlock &root) 36 : 37 ::Directory(parent), 38 fVolume(volume) 39 { 40 fNode.SetTo(root.BlockData(), root.BlockSize()); 41 } 42 43 44 Directory::~Directory() 45 { 46 free(fNode.BlockData()); 47 } 48 49 50 status_t 51 Directory::InitCheck() 52 { 53 return fNode.ValidateCheckSum(); 54 } 55 56 57 status_t 58 Directory::Open(void **_cookie, int mode) 59 { 60 _inherited::Open(_cookie, mode); 61 62 HashIterator *iterator = new(nothrow) HashIterator(fVolume.Device(), fNode); 63 if (iterator == NULL) 64 return B_NO_MEMORY; 65 66 if (iterator->InitCheck() != B_OK) { 67 delete iterator; 68 return B_NO_MEMORY; 69 } 70 71 *_cookie = (void *)iterator; 72 return B_OK; 73 } 74 75 76 status_t 77 Directory::Close(void *cookie) 78 { 79 _inherited::Close(cookie); 80 81 delete (HashIterator *)cookie; 82 return B_OK; 83 } 84 85 86 Node * 87 Directory::Lookup(const char *name, bool traverseLinks) 88 { 89 if (!strcmp(name, ".")) { 90 Acquire(); 91 return this; 92 } 93 94 HashIterator iterator(fVolume.Device(), fNode); 95 if (iterator.InitCheck() != B_OK) 96 return NULL; 97 98 iterator.Goto(fNode.HashIndexFor(fVolume.Type(), name)); 99 100 NodeBlock *node; 101 int32 block; 102 while ((node = iterator.GetNext(block)) != NULL) { 103 char fileName[FFS_NAME_LENGTH]; 104 if (node->GetName(fileName, sizeof(fileName)) == B_OK 105 && !strcmp(name, fileName)) { 106 if (node->IsFile()) 107 return new(nothrow) File(fVolume, block); 108 if (node->IsDirectory()) 109 return new(nothrow) Directory(fVolume, this, block); 110 111 return NULL; 112 } 113 } 114 return NULL; 115 } 116 117 118 status_t 119 Directory::GetNextEntry(void *cookie, char *name, size_t size) 120 { 121 HashIterator *iterator = (HashIterator *)cookie; 122 int32 block; 123 124 NodeBlock *node = iterator->GetNext(block); 125 if (node == NULL) 126 return B_ENTRY_NOT_FOUND; 127 128 return node->GetName(name, size); 129 } 130 131 132 status_t 133 Directory::GetNextNode(void *cookie, Node **_node) 134 { 135 return B_ERROR; 136 } 137 138 139 status_t 140 Directory::Rewind(void *cookie) 141 { 142 HashIterator *iterator = (HashIterator *)cookie; 143 iterator->Rewind(); 144 145 return B_OK; 146 } 147 148 149 bool 150 Directory::IsEmpty() 151 { 152 int32 index; 153 return fNode.FirstHashValue(index) == -1; 154 } 155 156 157 status_t 158 Directory::GetName(char *name, size_t size) const 159 { 160 return fNode.GetName(name, size); 161 } 162 163 164 ino_t 165 Directory::Inode() const 166 { 167 return fNode.HeaderKey(); 168 } 169 170 } // namespace FFS 171