xref: /haiku/src/add-ons/kernel/file_systems/netfs/client/netfs.cpp (revision 7749d0bb0c358a3279b1b9cc76d8376e900130a5)
1 // netfs.cpp
2 
3 #include <new>
4 
5 #include <KernelExport.h>
6 #include <fsproto.h>
7 
8 #include "DebugSupport.h"
9 #include "Node.h"
10 #include "ObjectTracker.h"
11 #include "QueryManager.h"
12 #include "RootVolume.h"
13 #include "VolumeManager.h"
14 
15 // #pragma mark -
16 // #pragma mark ----- prototypes -----
17 
18 extern "C" {
19 
20 // fs
21 static int netfs_mount(nspace_id nsid, const char *device, ulong flags,
22 				void *parameters, size_t len, void **data, vnode_id *rootID);
23 static int netfs_unmount(void *ns);
24 //static int netfs_sync(void *ns);
25 static int netfs_read_fs_stat(void *ns, struct fs_info *info);
26 //static int netfs_write_fs_stat(void *ns, struct fs_info *info, long mask);
27 
28 // vnodes
29 static int netfs_read_vnode(void *ns, vnode_id vnid, char reenter,
30 				void **node);
31 static int netfs_write_vnode(void *ns, void *node, char reenter);
32 static int netfs_remove_vnode(void *ns, void *node, char reenter);
33 
34 // nodes
35 //static int netfs_fsync(void *ns, void *node);
36 static int netfs_read_stat(void *ns, void *node, struct stat *st);
37 static int netfs_write_stat(void *ns, void *node, struct stat *st,
38 				long mask);
39 static int netfs_access(void *ns, void *node, int mode);
40 
41 // files
42 static int netfs_create(void *ns, void *dir, const char *name,
43 				int openMode, int mode, vnode_id *vnid, void **cookie);
44 static int netfs_open(void *ns, void *node, int openMode, void **cookie);
45 static int netfs_close(void *ns, void *node, void *cookie);
46 static int netfs_free_cookie(void *ns, void *node, void *cookie);
47 static int netfs_read(void *ns, void *node, void *cookie, off_t pos,
48 				void *buffer, size_t *bufferSize);
49 static int netfs_write(void *ns, void *node, void *cookie, off_t pos,
50 				const void *buffer, size_t *bufferSize);
51 static int netfs_ioctl(void *ns, void *node, void *cookie, int cmd,
52 				void *buffer, size_t bufferSize);
53 //static int netfs_setflags(void *ns, void *node, void *cookie, int flags);
54 
55 // hard links / symlinks
56 static int netfs_link(void *ns, void *dir, const char *name, void *node);
57 static int netfs_unlink(void *ns, void *dir, const char *name);
58 static int netfs_symlink(void *ns, void *dir, const char *name,
59 				const char *path);
60 static int netfs_read_link(void *ns, void *node, char *buffer,
61 				size_t *bufferSize);
62 static int netfs_rename(void *ns, void *oldDir, const char *oldName,
63 				void *newDir, const char *newName);
64 
65 // directories
66 static int netfs_mkdir(void *ns, void *dir, const char *name, int mode);
67 static int netfs_rmdir(void *ns, void *dir, const char *name);
68 static int netfs_open_dir(void *ns, void *node, void **cookie);
69 static int netfs_close_dir(void *ns, void *node, void *cookie);
70 static int netfs_free_dir_cookie(void *ns, void *node, void *cookie);
71 static int netfs_read_dir(void *ns, void *node, void *cookie,
72 				long *count, struct dirent *buffer, size_t bufferSize);
73 static int netfs_rewind_dir(void *ns, void *node, void *cookie);
74 static int netfs_walk(void *ns, void *dir, const char *entryName,
75 				char **resolvedPath, vnode_id *vnid);
76 
77 // attributes
78 static int netfs_open_attrdir(void *ns, void *node, void **cookie);
79 static int netfs_close_attrdir(void *ns, void *node, void *cookie);
80 static int netfs_free_attrdir_cookie(void *ns, void *node, void *cookie);
81 static int netfs_read_attrdir(void *ns, void *node, void *cookie,
82 				long *count, struct dirent *buffer, size_t bufferSize);
83 static int netfs_read_attr(void *ns, void *node, const char *name,
84 				int type, void *buffer, size_t *bufferSize, off_t pos);
85 static int netfs_rewind_attrdir(void *ns, void *node, void *cookie);
86 static int netfs_write_attr(void *ns, void *node, const char *name,
87 				int type, const void *buffer, size_t *bufferSize, off_t pos);
88 static int netfs_remove_attr(void *ns, void *node, const char *name);
89 static int netfs_rename_attr(void *ns, void *node, const char *oldName,
90 				const char *newName);
91 static int netfs_stat_attr(void *ns, void *node, const char *name,
92 				struct attr_info *attrInfo);
93 
94 // queries
95 static int netfs_open_query(void *ns, const char *queryString, ulong flags,
96 				port_id port, long token, void **cookie);
97 static int netfs_close_query(void *ns, void *cookie);
98 static int netfs_free_query_cookie(void *ns, void *node, void *cookie);
99 static int netfs_read_query(void *ns, void *cookie, long *count,
100 				struct dirent *buffer, size_t bufferSize);
101 
102 } // extern "C"
103 
104 /* vnode_ops struct. Fill this in to tell the kernel how to call
105 	functions in your driver.
106 */
107 vnode_ops fs_entry = {
108 	&netfs_read_vnode,				// read_vnode
109 	&netfs_write_vnode,				// write_vnode
110 	&netfs_remove_vnode,			// remove_vnode
111 	NULL,							// secure_vnode (not needed)
112 	&netfs_walk,					// walk
113 	&netfs_access,					// access
114 	&netfs_create,					// create
115 	&netfs_mkdir,					// mkdir
116 	&netfs_symlink,					// symlink
117 	&netfs_link,					// link
118 	&netfs_rename,					// rename
119 	&netfs_unlink,					// unlink
120 	&netfs_rmdir,					// rmdir
121 	&netfs_read_link,				// readlink
122 	&netfs_open_dir,				// opendir
123 	&netfs_close_dir,				// closedir
124 	&netfs_free_dir_cookie,			// free_dircookie
125 	&netfs_rewind_dir,				// rewinddir
126 	&netfs_read_dir,				// readdir
127 	&netfs_open,					// open file
128 	&netfs_close,					// close file
129 	&netfs_free_cookie,				// free cookie
130 	&netfs_read,					// read file
131 	&netfs_write,					// write file
132 	NULL,							// readv
133 	NULL,							// writev
134 	&netfs_ioctl,					// ioctl
135 	NULL,							// setflags file
136 	&netfs_read_stat,				// read stat
137 	&netfs_write_stat,				// write stat
138 	NULL,							// fsync
139 	NULL,							// initialize
140 	&netfs_mount,					// mount
141 	&netfs_unmount,					// unmount
142 	NULL,							// sync
143 	&netfs_read_fs_stat,			// read fs stat
144 	NULL,							// write fs stat
145 	NULL,							// select
146 	NULL,							// deselect
147 
148 	NULL,							// open index dir
149 	NULL,							// close index dir
150 	NULL,							// free index dir cookie
151 	NULL,							// rewind index dir
152 	NULL,							// read index dir
153 	NULL,							// create index
154 	NULL,							// remove index
155 	NULL,							// rename index
156 	NULL,							// stat index
157 
158 	&netfs_open_attrdir,			// open attr dir
159 	&netfs_close_attrdir,			// close attr dir
160 	&netfs_free_attrdir_cookie,		// free attr dir cookie
161 	&netfs_rewind_attrdir,			// rewind attr dir
162 	&netfs_read_attrdir,			// read attr dir
163 	&netfs_write_attr,				// write attr
164 	&netfs_read_attr,				// read attr
165 	&netfs_remove_attr,				// remove attr
166 	&netfs_rename_attr,				// rename attr
167 	&netfs_stat_attr,				// stat attr
168 
169 	&netfs_open_query,				// open query
170 	&netfs_close_query,				// close query
171 	&netfs_free_query_cookie,		// free query cookie
172 	&netfs_read_query,				// read query
173 };
174 
175 int32 api_version = B_CUR_FS_API_VERSION;
176 
177 // #pragma mark -
178 // #pragma mark ----- fs -----
179 
180 // netfs_mount
181 static
182 int
183 netfs_mount(nspace_id nsid, const char *device, ulong flags,
184 	void *parameters, size_t len, void **data, vnode_id *rootID)
185 {
186 	status_t error = B_OK;
187 	init_debugging();
188 
189 	#ifdef DEBUG_OBJECT_TRACKING
190 		ObjectTracker::InitDefault();
191 	#endif
192 
193 	// create and init the volume manager
194 	VolumeManager* volumeManager = new(std::nothrow) VolumeManager(nsid, flags);
195 	Volume* rootVolume = NULL;
196 	if (volumeManager) {
197 		error = volumeManager->MountRootVolume(device,
198 			(const char*)parameters, len, &rootVolume);
199 		if (error != B_OK) {
200 			delete volumeManager;
201 			volumeManager = NULL;
202 		}
203 	} else
204 		error = B_NO_MEMORY;
205 	VolumePutter _(rootVolume);
206 
207 	// set results
208 	if (error == B_OK) {
209 		*data = volumeManager;
210 		*rootID = rootVolume->GetRootID();
211 	} else {
212 		#ifdef DEBUG_OBJECT_TRACKING
213 			ObjectTracker::ExitDefault();
214 		#endif
215 		exit_debugging();
216 	}
217 	return error;
218 }
219 
220 // netfs_unmount
221 static
222 int
223 netfs_unmount(void *ns)
224 {
225 	VolumeManager* volumeManager = (VolumeManager*)ns;
226 
227 	PRINT(("netfs_unmount()\n"));
228 
229 	volumeManager->UnmountRootVolume();
230 	delete volumeManager;
231 
232 	#ifdef DEBUG_OBJECT_TRACKING
233 		ObjectTracker::ExitDefault();
234 	#endif
235 
236 	PRINT(("netfs_unmount() done\n"));
237 
238 	exit_debugging();
239 	return B_OK;
240 }
241 
242 #if 0 // not used
243 
244 // netfs_sync
245 static
246 int
247 netfs_sync(void *ns)
248 {
249 	VolumeManager* volumeManager = (VolumeManager*)ns;
250 	Volume* volume = volumeManager->GetRootVolume();
251 	VolumePutter _(volume);
252 
253 	PRINT(("netfs_sync(%p)\n", ns));
254 
255 	status_t error = B_BAD_VALUE;
256 	if (volume)
257 		error = volume->Sync();
258 
259 	PRINT(("netfs_sync() done: %lx \n", error));
260 
261 	return error;
262 }
263 
264 #endif
265 
266 // netfs_read_fs_stat
267 static
268 int
269 netfs_read_fs_stat(void *ns, struct fs_info *info)
270 {
271 	VolumeManager* volumeManager = (VolumeManager*)ns;
272 	Volume* volume = volumeManager->GetRootVolume();
273 	VolumePutter _(volume);
274 
275 	PRINT(("netfs_read_fs_stat(%p, %p)\n", ns, info));
276 
277 	status_t error = B_BAD_VALUE;
278 	if (volume)
279 		error = volume->ReadFSStat(info);
280 
281 	PRINT(("netfs_read_fs_stat() done: %lx \n", error));
282 
283 	return error;
284 }
285 
286 #if 0 // not used
287 
288 // netfs_write_fs_stat
289 static
290 int
291 netfs_write_fs_stat(void *ns, struct fs_info *info, long mask)
292 {
293 	VolumeManager* volumeManager = (VolumeManager*)ns;
294 	Volume* volume = volumeManager->GetRootVolume();
295 	VolumePutter _(volume);
296 
297 	PRINT(("netfs_write_fs_stat(%p, %p, %ld)\n", ns, info, mask));
298 
299 	status_t error = B_BAD_VALUE;
300 	if (volume)
301 		error = volume->WriteFSStat(info, mask);
302 
303 	PRINT(("netfs_write_fs_stat() done: %lx \n", error));
304 
305 	return error;
306 }
307 
308 #endif
309 
310 // #pragma mark -
311 // #pragma mark ----- vnodes -----
312 
313 // netfs_read_vnode
314 static
315 int
316 netfs_read_vnode(void *ns, vnode_id vnid, char reenter, void **node)
317 {
318 	VolumeManager* volumeManager = (VolumeManager*)ns;
319 	Volume* volume = volumeManager->GetVolume(vnid);
320 	VolumePutter _(volume);
321 
322 	PRINT(("netfs_read_vnode(%p, %Ld, %d, %p)\n", ns, vnid, reenter, node));
323 
324 	status_t error = B_BAD_VALUE;
325 	if (volume)
326 		error = volume->ReadVNode(vnid, reenter, (Node**)node);
327 
328 	PRINT(("netfs_read_vnode() done: (%lx, %p)\n", error, *node));
329 
330 	return error;
331 }
332 
333 // netfs_write_vnode
334 static
335 int
336 netfs_write_vnode(void *ns, void *_node, char reenter)
337 {
338 	Node* node = (Node*)_node;
339 // DANGER: If dbg_printf() is used, this thread will enter another FS and
340 // even perform a write operation. The is dangerous here, since this hook
341 // may be called out of the other FSs, since, for instance a put_vnode()
342 // called from another FS may cause the VFS layer to free vnodes and thus
343 // invoke this hook.
344 //	PRINT(("netfs_write_vnode(%p, %p, %d)\n", ns, node, reenter));
345 	status_t error = node->GetVolume()->WriteVNode(node, reenter);
346 //	PRINT(("netfs_write_vnode() done: %lx\n", error));
347 	return error;
348 }
349 
350 // netfs_remove_vnode
351 static
352 int
353 netfs_remove_vnode(void *ns, void *_node, char reenter)
354 {
355 	Node* node = (Node*)_node;
356 // DANGER: See netfs_write_vnode().
357 //	PRINT(("netfs_remove_vnode(%p, %p, %d)\n", ns, node, reenter));
358 	status_t error = node->GetVolume()->RemoveVNode(node, reenter);
359 //	PRINT(("netfs_remove_vnode() done: %lx\n", error));
360 	return error;
361 }
362 
363 // #pragma mark -
364 // #pragma mark ----- nodes -----
365 
366 #if 0 // not used
367 
368 // netfs_fsync
369 static
370 int
371 netfs_fsync(void *ns, void *_node)
372 {
373 	Node* node = (Node*)_node;
374 	PRINT(("netfs_fsync(%p, %p)\n", ns, node));
375 	status_t error = node->GetVolume()->FSync(node);
376 	PRINT(("netfs_fsync() done: %lx\n", error));
377 	return error;
378 }
379 
380 #endif
381 
382 // netfs_read_stat
383 static
384 int
385 netfs_read_stat(void *ns, void *_node, struct stat *st)
386 {
387 	Node* node = (Node*)_node;
388 	PRINT(("netfs_read_stat(%p, %p, %p)\n", ns, node, st));
389 	status_t error = node->GetVolume()->ReadStat(node, st);
390 	PRINT(("netfs_read_stat() done: %lx\n", error));
391 	return error;
392 }
393 
394 // netfs_write_stat
395 static
396 int
397 netfs_write_stat(void *ns, void *_node, struct stat *st, long mask)
398 {
399 	Node* node = (Node*)_node;
400 	PRINT(("netfs_write_stat(%p, %p, %p, %ld)\n", ns, node, st, mask));
401 	status_t error = node->GetVolume()->WriteStat(node, st, mask);
402 	PRINT(("netfs_write_stat() done: %lx\n", error));
403 	return error;
404 }
405 
406 // netfs_access
407 static
408 int
409 netfs_access(void *ns, void *_node, int mode)
410 {
411 	Node* node = (Node*)_node;
412 	PRINT(("netfs_access(%p, %p, %d)\n", ns, node, mode));
413 	status_t error = node->GetVolume()->Access(node, mode);
414 	PRINT(("netfs_access() done: %lx\n", error));
415 	return error;
416 }
417 
418 // #pragma mark -
419 // #pragma mark ----- files -----
420 
421 // netfs_create
422 static
423 int
424 netfs_create(void *ns, void *_dir, const char *name, int openMode, int mode,
425 	vnode_id *vnid, void **cookie)
426 {
427 	Node* dir = (Node*)_dir;
428 	PRINT(("netfs_create(%p, %p, `%s', %d, %d, %p, %p)\n", ns, dir,
429 		name, openMode, mode, vnid, cookie));
430 	status_t error = dir->GetVolume()->Create(dir, name, openMode, mode, vnid,
431 		cookie);
432 	PRINT(("netfs_create() done: (%lx, %Ld, %p)\n", error, *vnid,
433 		*cookie));
434 	return error;
435 }
436 
437 // netfs_open
438 static
439 int
440 netfs_open(void *ns, void *_node, int openMode, void **cookie)
441 {
442 	Node* node = (Node*)_node;
443 	PRINT(("netfs_open(%p, %p, %d)\n", ns, node, openMode));
444 	status_t error = node->GetVolume()->Open(node, openMode, cookie);
445 	PRINT(("netfs_open() done: (%lx, %p)\n", error, *cookie));
446 	return error;
447 }
448 
449 // netfs_close
450 static
451 int
452 netfs_close(void *ns, void *_node, void *cookie)
453 {
454 	Node* node = (Node*)_node;
455 	PRINT(("netfs_close(%p, %p, %p)\n", ns, node, cookie));
456 	status_t error = node->GetVolume()->Close(node, cookie);
457 	PRINT(("netfs_close() done: %lx\n", error));
458 	return error;
459 }
460 
461 // netfs_free_cookie
462 static
463 int
464 netfs_free_cookie(void *ns, void *_node, void *cookie)
465 {
466 	Node* node = (Node*)_node;
467 	PRINT(("netfs_free_cookie(%p, %p, %p)\n", ns, node, cookie));
468 	status_t error = node->GetVolume()->FreeCookie(node, cookie);
469 	PRINT(("netfs_free_cookie() done: %lx\n", error));
470 	return error;
471 }
472 
473 // netfs_read
474 static
475 int
476 netfs_read(void *ns, void *_node, void *cookie, off_t pos, void *buffer,
477 	size_t *bufferSize)
478 {
479 	Node* node = (Node*)_node;
480 	PRINT(("netfs_read(%p, %p, %p, %Ld, %p, %lu)\n", ns, node, cookie, pos,
481 		buffer, *bufferSize));
482 	status_t error = node->GetVolume()->Read(node, cookie, pos, buffer,
483 		*bufferSize, bufferSize);
484 	PRINT(("netfs_read() done: (%lx, %lu)\n", error, *bufferSize));
485 	return error;
486 }
487 
488 // netfs_write
489 static
490 int
491 netfs_write(void *ns, void *_node, void *cookie, off_t pos,
492 	const void *buffer, size_t *bufferSize)
493 {
494 	Node* node = (Node*)_node;
495 	PRINT(("netfs_write(%p, %p, %p, %Ld, %p, %lu)\n", ns, node, cookie, pos,
496 		buffer, *bufferSize));
497 	status_t error = node->GetVolume()->Write(node, cookie, pos, buffer,
498 		*bufferSize, bufferSize);
499 	PRINT(("netfs_write() done: (%lx, %lu)\n", error, *bufferSize));
500 	return error;
501 }
502 
503 // netfs_ioctl
504 static
505 int
506 netfs_ioctl(void *ns, void *_node, void *cookie, int cmd, void *buffer,
507 	size_t bufferSize)
508 {
509 	Node* node = (Node*)_node;
510 	PRINT(("netfs_ioctl(%p, %p, %p, %d, %p, %lu)\n", ns, node, cookie, cmd,
511 		buffer, bufferSize));
512 	status_t error = node->GetVolume()->IOCtl(node, cookie, cmd, buffer,
513 		bufferSize);
514 	PRINT(("netfs_ioctl() done: (%lx)\n", error));
515 	return error;
516 }
517 
518 // netfs_setflags
519 //static
520 //int
521 //netfs_setflags(void *ns, void *_node, void *cookie, int flags)
522 //{
523 //	Node* node = (Node*)_node;
524 //	PRINT(("netfs_setflags(%p, %p, %p, %d)\n", ns, node, cookie, flags));
525 //	status_t error = node->GetVolume()->SetFlags(node, cookie, flags);
526 //	PRINT(("netfs_setflags() done: (%lx)\n", error));
527 //	return error;
528 //}
529 
530 // #pragma mark -
531 // #pragma mark ----- hard links / symlinks -----
532 
533 // netfs_link
534 static
535 int
536 netfs_link(void *ns, void *_dir, const char *name, void *_node)
537 {
538 	Node* dir = (Node*)_dir;
539 	Node* node = (Node*)_node;
540 	PRINT(("netfs_link(%p, %p, `%s', %p)\n", ns, dir, name, node));
541 	status_t error = dir->GetVolume()->Link(dir, name, node);
542 	PRINT(("netfs_link() done: (%lx)\n", error));
543 	return error;
544 }
545 
546 // netfs_unlink
547 static
548 int
549 netfs_unlink(void *ns, void *_dir, const char *name)
550 {
551 	Node* dir = (Node*)_dir;
552 	PRINT(("netfs_unlink(%p, %p, `%s')\n", ns, dir, name));
553 	status_t error = dir->GetVolume()->Unlink(dir, name);
554 	PRINT(("netfs_unlink() done: (%lx)\n", error));
555 	return error;
556 }
557 
558 // netfs_symlink
559 static
560 int
561 netfs_symlink(void *ns, void *_dir, const char *name, const char *path)
562 {
563 	Node* dir = (Node*)_dir;
564 	PRINT(("netfs_symlink(%p, %p, `%s', `%s')\n", ns, dir, name, path));
565 	status_t error = dir->GetVolume()->Symlink(dir, name, path);
566 	PRINT(("netfs_symlink() done: (%lx)\n", error));
567 	return error;
568 }
569 
570 // netfs_read_link
571 static
572 int
573 netfs_read_link(void *ns, void *_node, char *buffer, size_t *bufferSize)
574 {
575 	Node* node = (Node*)_node;
576 	PRINT(("netfs_read_link(%p, %p, %p, %lu)\n", ns, node, buffer,
577 		*bufferSize));
578 	status_t error = node->GetVolume()->ReadLink(node, buffer, *bufferSize,
579 		bufferSize);
580 	PRINT(("netfs_read_link() done: (%lx, %lu)\n", error, *bufferSize));
581 	return error;
582 }
583 
584 // netfs_rename
585 static
586 int
587 netfs_rename(void *ns, void *_oldDir, const char *oldName, void *_newDir,
588 	const char *newName)
589 {
590 	Node* oldDir = (Node*)_oldDir;
591 	Node* newDir = (Node*)_newDir;
592 	PRINT(("netfs_rename(%p, %p, `%s', %p, `%s')\n", ns, oldDir, oldName,
593 		newDir, newName));
594 	status_t error = oldDir->GetVolume()->Rename(oldDir, oldName,
595 		newDir, newName);
596 	PRINT(("netfs_rename() done: (%lx)\n", error));
597 	return error;
598 }
599 
600 // #pragma mark -
601 // #pragma mark ----- directories -----
602 
603 // netfs_mkdir
604 static
605 int
606 netfs_mkdir(void *ns, void *_dir, const char *name, int mode)
607 {
608 	Node* dir = (Node*)_dir;
609 	PRINT(("netfs_mkdir(%p, %p, `%s', %d)\n", ns, dir, name, mode));
610 	status_t error = dir->GetVolume()->MkDir(dir, name, mode);
611 	PRINT(("netfs_mkdir() done: (%lx)\n", error));
612 	return error;
613 }
614 
615 // netfs_rmdir
616 static
617 int
618 netfs_rmdir(void *ns, void *_dir, const char *name)
619 {
620 	Node* dir = (Node*)_dir;
621 	PRINT(("netfs_rmdir(%p, %p, `%s')\n", ns, dir, name));
622 	status_t error = dir->GetVolume()->RmDir(dir, name);
623 	PRINT(("netfs_rmdir() done: (%lx)\n", error));
624 	return error;
625 }
626 
627 // netfs_open_dir
628 static
629 int
630 netfs_open_dir(void *ns, void *_node, void **cookie)
631 {
632 	Node* node = (Node*)_node;
633 	PRINT(("netfs_open_dir(%p, %p)\n", ns, node));
634 	status_t error = node->GetVolume()->OpenDir(node, cookie);
635 	PRINT(("netfs_open_dir() done: (%lx, %p)\n", error, *cookie));
636 	return error;
637 }
638 
639 // netfs_close_dir
640 static
641 int
642 netfs_close_dir(void *ns, void *_node, void *cookie)
643 {
644 	Node* node = (Node*)_node;
645 	PRINT(("netfs_close_dir(%p, %p, %p)\n", ns, node, cookie));
646 	status_t error = node->GetVolume()->CloseDir(node, cookie);
647 	PRINT(("netfs_close_dir() done: %lx\n", error));
648 	return error;
649 }
650 
651 // netfs_free_dir_cookie
652 static
653 int
654 netfs_free_dir_cookie(void *ns, void *_node, void *cookie)
655 {
656 	Node* node = (Node*)_node;
657 	PRINT(("netfs_free_dir_cookie(%p, %p, %p)\n", ns, node, cookie));
658 	status_t error = node->GetVolume()->FreeDirCookie(node, cookie);
659 	PRINT(("netfs_free_dir_cookie() done: %lx \n", error));
660 	return error;
661 }
662 
663 // netfs_read_dir
664 static
665 int
666 netfs_read_dir(void *ns, void *_node, void *cookie, long *count,
667 	struct dirent *buffer, size_t bufferSize)
668 {
669 	Node* node = (Node*)_node;
670 	PRINT(("netfs_read_dir(%p, %p, %p, %ld, %p, %lu)\n", ns, node, cookie,
671 		*count, buffer, bufferSize));
672 	status_t error = node->GetVolume()->ReadDir(node, cookie, buffer,
673 		bufferSize, *count, count);
674 	PRINT(("netfs_read_dir() done: (%lx, %ld)\n", error, *count));
675 	#if DEBUG
676 		dirent* entry = buffer;
677 		for (int32 i = 0; i < *count; i++) {
678 			// R5's kernel vsprintf() doesn't seem to know `%.<number>s', so
679 			// we need to work around.
680 			char name[B_FILE_NAME_LENGTH];
681 			int nameLen = strnlen(entry->d_name, B_FILE_NAME_LENGTH - 1);
682 			strncpy(name, entry->d_name, nameLen);
683 			name[nameLen] = '\0';
684 			PRINT(("  entry: d_dev: %ld, d_pdev: %ld, d_ino: %Ld, d_pino: %Ld, "
685 				"d_reclen: %hu, d_name: `%s'\n",
686 				entry->d_dev, entry->d_pdev, entry->d_ino, entry->d_pino,
687 				entry->d_reclen, name));
688 			entry = (dirent*)((char*)entry + entry->d_reclen);
689 		}
690 	#endif
691 
692 	return error;
693 }
694 
695 // netfs_rewind_dir
696 static
697 int
698 netfs_rewind_dir(void *ns, void *_node, void *cookie)
699 {
700 	Node* node = (Node*)_node;
701 	PRINT(("netfs_rewind_dir(%p, %p, %p)\n", ns, node, cookie));
702 	status_t error = node->GetVolume()->RewindDir(node, cookie);
703 	PRINT(("netfs_rewind_dir() done: %lx\n", error));
704 	return error;
705 }
706 
707 // netfs_walk
708 static
709 int
710 netfs_walk(void *ns, void *_dir, const char *entryName,
711 	char **resolvedPath, vnode_id *vnid)
712 {
713 	Node* dir = (Node*)_dir;
714 	PRINT(("netfs_walk(%p, %p, `%s', %p, %p)\n", ns, dir,
715 		entryName, resolvedPath, vnid));
716 	status_t error = dir->GetVolume()->Walk(dir, entryName, resolvedPath, vnid);
717 	PRINT(("netfs_walk() done: (%lx, `%s', %Ld)\n", error,
718 		(resolvedPath ? *resolvedPath : NULL), *vnid));
719 	return error;
720 }
721 
722 // #pragma mark -
723 // #pragma mark ----- attributes -----
724 
725 // netfs_open_attrdir
726 static
727 int
728 netfs_open_attrdir(void *ns, void *_node, void **cookie)
729 {
730 	Node* node = (Node*)_node;
731 	PRINT(("netfs_open_attrdir(%p, %p)\n", ns, node));
732 	status_t error = node->GetVolume()->OpenAttrDir(node, cookie);
733 	PRINT(("netfs_open_attrdir() done: (%lx, %p)\n", error, *cookie));
734 	return error;
735 }
736 
737 // netfs_close_attrdir
738 static
739 int
740 netfs_close_attrdir(void *ns, void *_node, void *cookie)
741 {
742 	Node* node = (Node*)_node;
743 	PRINT(("netfs_close_attrdir(%p, %p, %p)\n", ns, node, cookie));
744 	status_t error = node->GetVolume()->CloseAttrDir(node, cookie);
745 	PRINT(("netfs_close_attrdir() done: (%lx)\n", error));
746 	return error;
747 }
748 
749 // netfs_free_attrdir_cookie
750 static
751 int
752 netfs_free_attrdir_cookie(void *ns, void *_node, void *cookie)
753 {
754 	Node* node = (Node*)_node;
755 	PRINT(("netfs_free_attrdir_cookie(%p, %p, %p)\n", ns, node, cookie));
756 	status_t error = node->GetVolume()->FreeAttrDirCookie(node, cookie);
757 	PRINT(("netfs_free_attrdir_cookie() done: (%lx)\n", error));
758 	return error;
759 }
760 
761 // netfs_read_attrdir
762 static
763 int
764 netfs_read_attrdir(void *ns, void *_node, void *cookie, long *count,
765 	struct dirent *buffer, size_t bufferSize)
766 {
767 	Node* node = (Node*)_node;
768 	PRINT(("netfs_read_attrdir(%p, %p, %p, %ld, %p, %lu)\n", ns, node,
769 		cookie, *count, buffer, bufferSize));
770 	status_t error = node->GetVolume()->ReadAttrDir(node, cookie, buffer,
771 		bufferSize, *count, count);
772 	PRINT(("netfs_read_attrdir() done: (%lx, %ld)\n", error, *count));
773 	return error;
774 }
775 
776 // netfs_rewind_attrdir
777 static
778 int
779 netfs_rewind_attrdir(void *ns, void *_node, void *cookie)
780 {
781 	Node* node = (Node*)_node;
782 	PRINT(("netfs_rewind_attrdir(%p, %p, %p)\n", ns, node, cookie));
783 	status_t error = node->GetVolume()->RewindAttrDir(node, cookie);
784 	PRINT(("netfs_rewind_attrdir() done: (%lx)\n", error));
785 	return error;
786 }
787 
788 // netfs_read_attr
789 static
790 int
791 netfs_read_attr(void *ns, void *_node, const char *name, int type,
792 	void *buffer, size_t *bufferSize, off_t pos)
793 {
794 	Node* node = (Node*)_node;
795 	PRINT(("netfs_read_attr(%p, %p, `%s', %d, %p, %lu, %Ld)\n", ns, node,
796 		name, type, buffer, *bufferSize, pos));
797 	status_t error = node->GetVolume()->ReadAttr(node, name, type, pos, buffer,
798 		*bufferSize, bufferSize);
799 	PRINT(("netfs_read_attr() done: (%lx, %ld)\n", error, *bufferSize));
800 	return error;
801 }
802 
803 // netfs_write_attr
804 static
805 int
806 netfs_write_attr(void *ns, void *_node, const char *name, int type,
807 	const void *buffer, size_t *bufferSize, off_t pos)
808 {
809 	Node* node = (Node*)_node;
810 	PRINT(("netfs_write_attr(%p, %p, `%s', %d, %p, %lu, %Ld)\n", ns, node,
811 		name, type, buffer, *bufferSize, pos));
812 	status_t error = node->GetVolume()->WriteAttr(node, name, type, pos, buffer,
813 		*bufferSize, bufferSize);
814 	PRINT(("netfs_write_attr() done: (%lx, %ld)\n", error, *bufferSize));
815 	return error;
816 }
817 
818 // netfs_remove_attr
819 static
820 int
821 netfs_remove_attr(void *ns, void *_node, const char *name)
822 {
823 	Node* node = (Node*)_node;
824 	PRINT(("netfs_remove_attr(%p, %p, `%s')\n", ns, node, name));
825 	status_t error = node->GetVolume()->RemoveAttr(node, name);
826 	PRINT(("netfs_remove_attr() done: (%lx)\n", error));
827 	return error;
828 }
829 
830 // netfs_rename_attr
831 static
832 int
833 netfs_rename_attr(void *ns, void *_node, const char *oldName,
834 	const char *newName)
835 {
836 	Node* node = (Node*)_node;
837 	PRINT(("netfs_rename_attr(%p, %p, `%s', `%s')\n", ns, node, oldName,
838 		newName));
839 	status_t error = node->GetVolume()->RenameAttr(node, oldName, newName);
840 	PRINT(("netfs_rename_attr() done: (%lx)\n", error));
841 	return error;
842 }
843 
844 // netfs_stat_attr
845 static
846 int
847 netfs_stat_attr(void *ns, void *_node, const char *name,
848 	struct attr_info *attrInfo)
849 {
850 	Node* node = (Node*)_node;
851 	PRINT(("netfs_stat_attr(%p, %p, `%s', %p)\n", ns, node, name,
852 		attrInfo));
853 	status_t error = node->GetVolume()->StatAttr(node, name, attrInfo);
854 	PRINT(("netfs_stat_attr() done: (%lx)\n", error));
855 	return error;
856 }
857 
858 // #pragma mark -
859 // #pragma mark ----- queries -----
860 
861 // netfs_open_query
862 static
863 int
864 netfs_open_query(void *ns, const char *queryString, ulong flags,
865 	port_id port, long token, void **cookie)
866 {
867 	VolumeManager* volumeManager = (VolumeManager*)ns;
868 	Volume* volume = volumeManager->GetRootVolume();
869 	VolumePutter _(volume);
870 
871 	PRINT(("netfs_open_query(%p, `%s', %lu, %ld, %ld, %p)\n", ns,
872 		queryString, flags, port, token, cookie));
873 
874 	status_t error = B_BAD_VALUE;
875 	if (volume) {
876 		error = volume->OpenQuery(queryString, flags, port, token,
877 			(QueryIterator**)cookie);
878 	}
879 
880 	PRINT(("netfs_open_query() done: (%lx, %p)\n", error, *cookie));
881 	return error;
882 }
883 
884 // netfs_close_query
885 static
886 int
887 netfs_close_query(void *ns, void *cookie)
888 {
889 	PRINT(("netfs_close_query(%p, %p)\n", ns, cookie));
890 
891 	status_t error = B_OK;
892 	// no-op: we don't use this hook
893 
894 	PRINT(("netfs_close_query() done: (%lx)\n", error));
895 	return error;
896 }
897 
898 // netfs_free_query_cookie
899 static
900 int
901 netfs_free_query_cookie(void *ns, void *node, void *cookie)
902 {
903 	VolumeManager* volumeManager = (VolumeManager*)ns;
904 	QueryIterator* iterator = (QueryIterator*)cookie;
905 
906 	PRINT(("netfs_free_query_cookie(%p, %p)\n", ns, cookie));
907 
908 	status_t error = B_OK;
909 	volumeManager->GetQueryManager()->PutIterator(iterator);
910 
911 	PRINT(("netfs_free_query_cookie() done: (%lx)\n", error));
912 	return error;
913 }
914 
915 // netfs_read_query
916 static
917 int
918 netfs_read_query(void *ns, void *cookie, long *count,
919 	struct dirent *buffer, size_t bufferSize)
920 {
921 	VolumeManager* volumeManager = (VolumeManager*)ns;
922 	Volume* volume = volumeManager->GetRootVolume();
923 	QueryIterator* iterator = (QueryIterator*)cookie;
924 	VolumePutter _(volume);
925 
926 	PRINT(("netfs_read_query(%p, %p, %ld, %p, %lu)\n", ns, cookie,
927 		*count, buffer, bufferSize));
928 
929 	status_t error = B_BAD_VALUE;
930 	if (volume) {
931 		error = volume->ReadQuery(iterator, buffer, bufferSize,
932 		*count, count);
933 	}
934 
935 	PRINT(("netfs_read_query() done: (%lx, %ld)\n", error, *count));
936 	return error;
937 }
938 
939