xref: /haiku/src/tests/system/kernel/file_corruption/fs/Node.cpp (revision 0f9dda9f00200c24373c4e90911605e013d42afb)
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