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
18 static inline uint64
current_time_nanos()19 current_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
Node(Volume * volume,uint64 blockIndex,const checksumfs_node & nodeData)28 Node::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
Node(Volume * volume,mode_t mode)41 Node::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
~Node()68 Node::~Node()
69 {
70 rw_lock_destroy(&fLock);
71 }
72
73
74 void
SetBlockIndex(uint64 blockIndex)75 Node::SetBlockIndex(uint64 blockIndex)
76 {
77 fBlockIndex = blockIndex;
78 }
79
80
81 status_t
InitForVFS()82 Node::InitForVFS()
83 {
84 return B_OK;
85 }
86
87
88 void
DeletingNode()89 Node::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
107 status_t
Resize(uint64 newSize,bool fillWithZeroes,Transaction & transaction)108 Node::Resize(uint64 newSize, bool fillWithZeroes, Transaction& transaction)
109 {
110 RETURN_ERROR(B_BAD_VALUE);
111 }
112
113
114 status_t
Read(off_t pos,void * buffer,size_t size,size_t & _bytesRead)115 Node::Read(off_t pos, void* buffer, size_t size, size_t& _bytesRead)
116 {
117 RETURN_ERROR(B_BAD_VALUE);
118 }
119
120
121 status_t
Write(off_t pos,const void * buffer,size_t size,size_t & _bytesWritten,bool & _sizeChanged)122 Node::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
129 status_t
Sync()130 Node::Sync()
131 {
132 return B_OK;
133 }
134
135
136 void
SetMode(uint32 mode)137 Node::SetMode(uint32 mode)
138 {
139 ASSERT((mode & S_IFMT) == (Mode() & S_IFMT));
140
141 fNode.mode = mode;
142 fNodeDataDirty = true;
143 }
144
145
146 void
SetAttributeType(uint32 type)147 Node::SetAttributeType(uint32 type)
148 {
149 fNode.attributeType = type;
150 fNodeDataDirty = true;
151 }
152
153
154 void
SetParentDirectory(uint32 blockIndex)155 Node::SetParentDirectory(uint32 blockIndex)
156 {
157 fNode.parentDirectory = blockIndex;
158 fNodeDataDirty = true;
159 }
160
161
162 void
SetAttributeDirectory(uint32 blockIndex)163 Node::SetAttributeDirectory(uint32 blockIndex)
164 {
165 fNode.attributeDirectory = blockIndex;
166 fNodeDataDirty = true;
167 }
168
169
170 void
SetHardLinks(uint32 value)171 Node::SetHardLinks(uint32 value)
172 {
173 fNode.hardLinks = value;
174 fNodeDataDirty = true;
175 }
176
177
178 void
SetUID(uint32 uid)179 Node::SetUID(uint32 uid)
180 {
181 fNode.uid = uid;
182 fNodeDataDirty = true;
183 }
184
185
186 void
SetGID(uint32 gid)187 Node::SetGID(uint32 gid)
188 {
189 fNode.gid = gid;
190 fNodeDataDirty = true;
191 }
192
193
194 void
SetSize(uint64 size)195 Node::SetSize(uint64 size)
196 {
197 fNode.size = size;
198 fNodeDataDirty = true;
199 }
200
201
202 void
SetAccessedTime(uint64 time)203 Node::SetAccessedTime(uint64 time)
204 {
205 fAccessedTime = time;
206 }
207
208
209 void
SetCreationTime(uint64 time)210 Node::SetCreationTime(uint64 time)
211 {
212 fNode.creationTime = time;
213 fNodeDataDirty = true;
214 }
215
216
217 void
SetModificationTime(uint64 time)218 Node::SetModificationTime(uint64 time)
219 {
220 fNode.modificationTime = time;
221 fNodeDataDirty = true;
222 }
223
224
225 void
SetChangeTime(uint64 time)226 Node::SetChangeTime(uint64 time)
227 {
228 fNode.changeTime = time;
229 fNodeDataDirty = true;
230 }
231
232
233 void
Touched(int32 mode)234 Node::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
250 void
RevertNodeData(const checksumfs_node & nodeData)251 Node::RevertNodeData(const checksumfs_node& nodeData)
252 {
253 fNode = nodeData;
254 fNodeDataDirty = false;
255 }
256
257
258 status_t
Flush(Transaction & transaction)259 Node::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
275 void
_Init()276 Node::_Init()
277 {
278 rw_lock_init(&fLock, "checkfs node");
279 }
280