1/* 2 * Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include "Node.h" 8 9#include <string.h> 10#include <sys/time.h> 11#include <unistd.h> 12 13#include "Block.h" 14#include "DebugSupport.h" 15#include "Volume.h" 16 17 18static inline uint64 19current_time_nanos() 20{ 21 timeval time; 22 gettimeofday(&time, NULL); 23 24 return (uint64)time.tv_sec * 1000000000 + (uint64)time.tv_usec * 1000; 25} 26 27 28Node::Node(Volume* volume, uint64 blockIndex, const checksumfs_node& nodeData) 29 : 30 fVolume(volume), 31 fBlockIndex(blockIndex), 32 fNode(nodeData), 33 fNodeDataDirty(false) 34{ 35 _Init(); 36 37 fAccessedTime = ModificationTime(); 38} 39 40 41Node::Node(Volume* volume, mode_t mode) 42 : 43 fVolume(volume), 44 fBlockIndex(0), 45 fNodeDataDirty(true) 46{ 47 _Init(); 48 49 memset(&fNode, 0, sizeof(fNode)); 50 51 fNode.mode = mode; 52 53 // set user/group 54 fNode.uid = geteuid(); 55 fNode.gid = getegid(); 56 57 // set the times 58 timeval time; 59 gettimeofday(&time, NULL); 60 61 fAccessedTime = current_time_nanos(); 62 fNode.creationTime = fAccessedTime; 63 fNode.modificationTime = fAccessedTime; 64 fNode.changeTime = fAccessedTime; 65} 66 67 68Node::~Node() 69{ 70 rw_lock_destroy(&fLock); 71} 72 73 74void 75Node::SetBlockIndex(uint64 blockIndex) 76{ 77 fBlockIndex = blockIndex; 78} 79 80 81status_t 82Node::InitForVFS() 83{ 84 return B_OK; 85} 86 87 88void 89Node::DeletingNode() 90{ 91 // delete the node's attribute directory 92 if (AttributeDirectory() == 0) 93 return; 94 95 Node* attributeDirectory; 96 if (fVolume->GetNode(AttributeDirectory(), attributeDirectory) == B_OK) { 97 fVolume->RemoveNode(attributeDirectory); 98 fVolume->PutNode(attributeDirectory); 99 } else { 100 ERROR("Failed to get attribute directory (at %" B_PRIu64 ") for " 101 "deleted node at %" B_PRIu64 "\n", AttributeDirectory(), 102 BlockIndex()); 103 } 104} 105 106 107status_t 108Node::Resize(uint64 newSize, bool fillWithZeroes, Transaction& transaction) 109{ 110 RETURN_ERROR(B_BAD_VALUE); 111} 112 113 114status_t 115Node::Read(off_t pos, void* buffer, size_t size, size_t& _bytesRead) 116{ 117 RETURN_ERROR(B_BAD_VALUE); 118} 119 120 121status_t 122Node::Write(off_t pos, const void* buffer, size_t size, size_t& _bytesWritten, 123 bool& _sizeChanged) 124{ 125 RETURN_ERROR(B_BAD_VALUE); 126} 127 128 129status_t 130Node::Sync() 131{ 132 return B_OK; 133} 134 135 136void 137Node::SetMode(uint32 mode) 138{ 139 ASSERT((mode & S_IFMT) == (Mode() & S_IFMT)); 140 141 fNode.mode = mode; 142 fNodeDataDirty = true; 143} 144 145 146void 147Node::SetAttributeType(uint32 type) 148{ 149 fNode.attributeType = type; 150 fNodeDataDirty = true; 151} 152 153 154void 155Node::SetParentDirectory(uint32 blockIndex) 156{ 157 fNode.parentDirectory = blockIndex; 158 fNodeDataDirty = true; 159} 160 161 162void 163Node::SetAttributeDirectory(uint32 blockIndex) 164{ 165 fNode.attributeDirectory = blockIndex; 166 fNodeDataDirty = true; 167} 168 169 170void 171Node::SetHardLinks(uint32 value) 172{ 173 fNode.hardLinks = value; 174 fNodeDataDirty = true; 175} 176 177 178void 179Node::SetUID(uint32 uid) 180{ 181 fNode.uid = uid; 182 fNodeDataDirty = true; 183} 184 185 186void 187Node::SetGID(uint32 gid) 188{ 189 fNode.gid = gid; 190 fNodeDataDirty = true; 191} 192 193 194void 195Node::SetSize(uint64 size) 196{ 197 fNode.size = size; 198 fNodeDataDirty = true; 199} 200 201 202void 203Node::SetAccessedTime(uint64 time) 204{ 205 fAccessedTime = time; 206} 207 208 209void 210Node::SetCreationTime(uint64 time) 211{ 212 fNode.creationTime = time; 213 fNodeDataDirty = true; 214} 215 216 217void 218Node::SetModificationTime(uint64 time) 219{ 220 fNode.modificationTime = time; 221 fNodeDataDirty = true; 222} 223 224 225void 226Node::SetChangeTime(uint64 time) 227{ 228 fNode.changeTime = time; 229 fNodeDataDirty = true; 230} 231 232 233void 234Node::Touched(int32 mode) 235{ 236 fAccessedTime = current_time_nanos(); 237 238 switch (mode) { 239 default: 240 case NODE_MODIFIED: 241 fNode.modificationTime = fAccessedTime; 242 case NODE_STAT_CHANGED: 243 fNode.changeTime = fAccessedTime; 244 case NODE_ACCESSED: 245 break; 246 } 247} 248 249 250void 251Node::RevertNodeData(const checksumfs_node& nodeData) 252{ 253 fNode = nodeData; 254 fNodeDataDirty = false; 255} 256 257 258status_t 259Node::Flush(Transaction& transaction) 260{ 261 if (!fNodeDataDirty) 262 return B_OK; 263 264 Block block; 265 if (!block.GetWritable(fVolume, fBlockIndex, transaction)) 266 return B_ERROR; 267 268 memcpy(block.Data(), &fNode, sizeof(fNode)); 269 270 fNodeDataDirty = false; 271 return B_OK; 272} 273 274 275void 276Node::_Init() 277{ 278 rw_lock_init(&fLock, "checkfs node"); 279} 280