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