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