xref: /haiku/src/add-ons/kernel/file_systems/netfs/server/NodeHandle.cpp (revision 4c8e85b316c35a9161f5a1c50ad70bc91c83a76f)
1 // NodeHandle.cpp
2 
3 #include "NodeHandle.h"
4 
5 #include <errno.h>
6 #include <fcntl.h>
7 #include <string.h>
8 #include <unistd.h>
9 #include <sys/stat.h>
10 
11 #include <fs_attr.h>
12 
13 #include "Compatibility.h"
14 #include "Directory.h"
15 #include "FDManager.h"
16 #include "Path.h"
17 
18 // TODO: Do the FD creation via the FDManager.
19 
20 // NodeHandle
21 
22 // constructor
23 NodeHandle::NodeHandle()
24 	: BReferenceable(),
25 	  Lockable(),
26 	  fCookie(-1),
27 	  fNodeRef()
28 {
29 }
30 
31 // destructor
32 NodeHandle::~NodeHandle()
33 {
34 }
35 
36 // GetStat
37 status_t
38 NodeHandle::GetStat(struct stat* st)
39 {
40 	int fd = GetFD();
41 	if (fd < 0)
42 		return B_ENTRY_NOT_FOUND;
43 
44 	if (fstat(fd, st) < 0)
45 		return errno;
46 
47 	return B_OK;
48 }
49 
50 // SetCookie
51 void
52 NodeHandle::SetCookie(int32 cookie)
53 {
54 	fCookie = cookie;
55 }
56 
57 // GetCookie
58 int32
59 NodeHandle::GetCookie() const
60 {
61 	return fCookie;
62 }
63 
64 // GetNodeRef
65 const NodeRef&
66 NodeHandle::GetNodeRef() const
67 {
68 	return fNodeRef;
69 }
70 
71 // GetFD
72 int
73 NodeHandle::GetFD() const
74 {
75 	return -1;
76 }
77 
78 
79 // #pragma mark -
80 
81 // FileHandle
82 
83 // constructor
84 FileHandle::FileHandle()
85 	: fFD(-1)
86 {
87 }
88 
89 // destructor
90 FileHandle::~FileHandle()
91 {
92 	Close();
93 }
94 
95 // Open
96 status_t
97 FileHandle::Open(Node* node, int openMode)
98 {
99 	if (!node)
100 		return B_BAD_VALUE;
101 
102 	openMode &= O_RWMASK | O_TRUNC | O_APPEND;
103 
104 	// get a path
105 	Path path;
106 	status_t error = node->GetPath(&path);
107 	if (error != B_OK)
108 		return error;
109 
110 	// open the file
111 	error = FDManager::Open(path.GetPath(), openMode | O_NOTRAVERSE, 0, fFD);
112 	if (error != B_OK)
113 		return error;
114 
115 	fNodeRef = node->GetNodeRef();
116 
117 	return B_OK;
118 }
119 
120 // Close
121 status_t
122 FileHandle::Close()
123 {
124 	if (fFD < 0)
125 		return B_BAD_VALUE;
126 
127 	status_t error = B_OK;
128 	if (close(fFD) < 0)
129 		error = errno;
130 	fFD = -1;
131 
132 	return error;
133 }
134 
135 // Read
136 status_t
137 FileHandle::Read(off_t pos, void* buffer, size_t size, size_t* _bytesRead)
138 {
139 	if (fFD < 0)
140 		return B_BAD_VALUE;
141 
142 	ssize_t bytesRead = read_pos(fFD, pos, buffer, size);
143 	if (bytesRead < 0)
144 		return errno;
145 
146 	*_bytesRead = bytesRead;
147 	return B_OK;
148 }
149 
150 // Write
151 status_t
152 FileHandle::Write(off_t pos, const void* buffer, size_t size,
153 	size_t* _bytesWritten)
154 {
155 	if (fFD < 0)
156 		return B_BAD_VALUE;
157 
158 	ssize_t bytesWritten = write_pos(fFD, pos, buffer, size);
159 	if (bytesWritten < 0)
160 		return errno;
161 
162 	*_bytesWritten = bytesWritten;
163 	return B_OK;
164 }
165 
166 // ReadAttr
167 status_t
168 FileHandle::ReadAttr(const char* name, uint32 type, off_t pos, void* buffer,
169 	size_t size, size_t* _bytesRead)
170 {
171 	if (fFD < 0)
172 		return B_BAD_VALUE;
173 
174 	ssize_t bytesRead = fs_read_attr(fFD, name, type, pos, buffer, size);
175 	if (bytesRead < 0)
176 		return errno;
177 
178 	*_bytesRead = bytesRead;
179 	return B_OK;
180 }
181 
182 // WriteAttr
183 status_t
184 FileHandle::WriteAttr(const char* name, uint32 type, off_t pos,
185 	const void* buffer, size_t size, size_t* _bytesWritten)
186 {
187 	if (fFD < 0)
188 		return B_BAD_VALUE;
189 
190 	ssize_t bytesWritten = fs_write_attr(fFD, name, type, pos, buffer, size);
191 	if (bytesWritten < 0)
192 		return errno;
193 
194 	*_bytesWritten = bytesWritten;
195 	return B_OK;
196 }
197 
198 // RemoveAttr
199 status_t
200 FileHandle::RemoveAttr(const char* name)
201 {
202 	if (fFD < 0)
203 		return B_BAD_VALUE;
204 
205 	return (fs_remove_attr(fFD, name) == 0 ? B_OK : errno);
206 }
207 
208 // StatAttr
209 status_t
210 FileHandle::StatAttr(const char* name, attr_info* info)
211 {
212 	if (fFD < 0)
213 		return B_BAD_VALUE;
214 
215 	return (fs_stat_attr(fFD, name, info) == 0 ? B_OK : errno);
216 }
217 
218 // GetFD
219 int
220 FileHandle::GetFD() const
221 {
222 	return fFD;
223 }
224 
225 
226 // #pragma mark -
227 
228 // DirIterator
229 
230 // constructor
231 DirIterator::DirIterator()
232 	: fDirectory(NULL)
233 {
234 }
235 
236 // destructor
237 DirIterator::~DirIterator()
238 {
239 	if (fDirectory)
240 		fDirectory->RemoveDirIterator(this);
241 }
242 
243 // IsValid
244 bool
245 DirIterator::IsValid() const
246 {
247 	return fDirectory;
248 }
249 
250 
251 // #pragma mark -
252 
253 // AttrDirIterator
254 
255 // constructor
256 AttrDirIterator::AttrDirIterator()
257 	: NodeHandle(),
258 	  fDir(NULL)
259 {
260 }
261 
262 // destructor
263 AttrDirIterator::~AttrDirIterator()
264 {
265 	Close();
266 }
267 
268 // Open
269 status_t
270 AttrDirIterator::Open(Node* node)
271 {
272 	if (!node)
273 		return B_BAD_VALUE;
274 
275 	// get a path
276 	Path path;
277 	status_t error = node->GetPath(&path);
278 	if (error != B_OK)
279 		return error;
280 
281 	// open the attribute directory
282 	error = FDManager::OpenAttrDir(path.GetPath(), fDir);
283 	if (error != B_OK)
284 		return errno;
285 
286 	fNodeRef = node->GetNodeRef();
287 
288 	return B_OK;
289 }
290 
291 // Close
292 status_t
293 AttrDirIterator::Close()
294 {
295 	if (!fDir)
296 		return B_BAD_VALUE;
297 
298 	status_t error = B_OK;
299 	if (fs_close_attr_dir(fDir) < 0)
300 		error = errno;
301 
302 	fDir = NULL;
303 	return error;
304 }
305 
306 // ReadDir
307 status_t
308 AttrDirIterator::ReadDir(dirent* _entry, int32 bufferSize,
309 	int32 count, int32* countRead, bool* done)
310 {
311 // TODO: Burst read.
312 	if (!fDir)
313 		return B_ENTRY_NOT_FOUND;
314 
315 	*countRead = 0;
316 	*done = false;
317 
318 	if (count == 0)
319 		return B_OK;
320 
321 	if (struct dirent* entry = fs_read_attr_dir(fDir)) {
322 		size_t entryLen = entry->d_name + strlen(entry->d_name) + 1
323 			- (char*)entry;
324 		memcpy(_entry, entry, entryLen);
325 		*countRead = 1;
326 	} else {
327 		*countRead = 0;
328 		*done = true;
329 	}
330 	return B_OK;
331 }
332 
333 // RewindDir
334 status_t
335 AttrDirIterator::RewindDir()
336 {
337 	if (!fDir)
338 		return B_ENTRY_NOT_FOUND;
339 
340 	fs_rewind_attr_dir(fDir);
341 
342 	return B_OK;
343 }
344 
345 // GetFD
346 int
347 AttrDirIterator::GetFD() const
348 {
349 	return dirfd(fDir);
350 }
351 
352 
353 // #pragma mark -
354 
355 // QueryListener
356 
357 // constructor
358 QueryListener::QueryListener()
359 {
360 }
361 
362 // destructor
363 QueryListener::~QueryListener()
364 {
365 }
366 
367 
368 // #pragma mark -
369 
370 // QueryHandle
371 
372 // constructor
373 QueryHandle::QueryHandle(port_id remotePort, int32 remoteToken)
374 	: NodeHandle(),
375 	  fRemotePort(remotePort),
376 	  fRemoteToken(remoteToken),
377 	  fQueries(),
378 	  fCurrentQuery(NULL),
379 	  fListener(NULL),
380 	  fClosed(false)
381 {
382 }
383 
384 // destructor
385 QueryHandle::~QueryHandle()
386 {
387 	Close();
388 }
389 
390 // SetQueryListener
391 void
392 QueryHandle::SetQueryListener(QueryListener* listener)
393 {
394 	fListener = listener;
395 }
396 
397 // GetQueryListener
398 QueryListener*
399 QueryHandle::GetQueryListener() const
400 {
401 	return fListener;
402 }
403 
404 // AddQuery
405 void
406 QueryHandle::AddQuery(Query* query)
407 {
408 	if (query) {
409 		fQueries.Insert(query);
410 		if (!fCurrentQuery)
411 			fCurrentQuery = query;
412 	}
413 }
414 
415 // RemoveQuery
416 void
417 QueryHandle::RemoveQuery(Query* query)
418 {
419 	if (query) {
420 		if (query == fCurrentQuery)
421 			fCurrentQuery = fQueries.GetNext(query);
422 		fQueries.Remove(query);
423 	}
424 }
425 
426 // GetRemotePort
427 port_id
428 QueryHandle::GetRemotePort() const
429 {
430 	return fRemotePort;
431 }
432 
433 // GetRemoteToken
434 int32
435 QueryHandle::GetRemoteToken() const
436 {
437 	return fRemoteToken;
438 }
439 
440 // Close
441 status_t
442 QueryHandle::Close()
443 {
444 	if (fClosed)
445 		return B_OK;
446 
447 	fCurrentQuery = NULL;
448 
449 	// delete all queries
450 	for (DoublyLinkedList<Query>::Iterator it = fQueries.GetIterator();
451 			it.HasNext();) {
452 		Query* query = it.Next();
453 		it.Remove();
454 		delete query;
455 	}
456 
457 	fClosed = true;
458 
459 	if (fListener)
460 		fListener->QueryHandleClosed(this);
461 
462 	return B_OK;
463 }
464 
465 // ReadDir
466 status_t
467 QueryHandle::ReadDir(dirent* entry, int32 count, int32* countRead)
468 {
469 	if (count == 0) {
470 		*countRead = 0;
471 		return B_OK;
472 	}
473 	while (fCurrentQuery) {
474 		int32 readEntries = fCurrentQuery->GetNextDirents(entry,
475 			offsetof(struct dirent, d_name) + B_FILE_NAME_LENGTH, 1);
476 		if (readEntries < 0)
477 			return readEntries;
478 		if (readEntries > 0) {
479 			*countRead = 1;
480 			return B_OK;
481 		}
482 		fCurrentQuery = fQueries.GetNext(fCurrentQuery);
483 	}
484 	*countRead = 0;
485 	return B_OK;
486 }
487 
488