xref: /haiku/src/add-ons/kernel/file_systems/netfs/client/netfs.cpp (revision e1b7c1c7ac1188a3b3e1694a958042468b95e781)
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
netfs_mount(nspace_id nsid,const char * device,ulong flags,void * parameters,size_t len,void ** data,vnode_id * rootID)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
netfs_unmount(void * ns)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: %" B_PRIx32 " \n", error);
260 
261 	return error;
262 }
263 
264 #endif
265 
266 // netfs_read_fs_stat
267 static
268 int
netfs_read_fs_stat(void * ns,struct fs_info * info)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: %" B_PRIx32 " \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: %" B_PRIx32 " \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
netfs_read_vnode(void * ns,vnode_id vnid,char reenter,void ** node)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, %" B_PRIdINO ", %d, %p)\n", ns, vnid, reenter,
323 		node);
324 
325 	status_t error = B_BAD_VALUE;
326 	if (volume)
327 		error = volume->ReadVNode(vnid, reenter, (Node**)node);
328 
329 	PRINT("netfs_read_vnode() done: (%" B_PRIx32 ", %p)\n", error, *node);
330 
331 	return error;
332 }
333 
334 // netfs_write_vnode
335 static
336 int
netfs_write_vnode(void * ns,void * _node,char reenter)337 netfs_write_vnode(void *ns, void *_node, char reenter)
338 {
339 	Node* node = (Node*)_node;
340 // DANGER: If dbg_printf() is used, this thread will enter another FS and
341 // even perform a write operation. The is dangerous here, since this hook
342 // may be called out of the other FSs, since, for instance a put_vnode()
343 // called from another FS may cause the VFS layer to free vnodes and thus
344 // invoke this hook.
345 //	PRINT(("netfs_write_vnode(%p, %p, %d)\n", ns, node, reenter));
346 	status_t error = node->GetVolume()->WriteVNode(node, reenter);
347 //	PRINT(("netfs_write_vnode() done: %" B_PRIx32 "\n", error));
348 	return error;
349 }
350 
351 // netfs_remove_vnode
352 static
353 int
netfs_remove_vnode(void * ns,void * _node,char reenter)354 netfs_remove_vnode(void *ns, void *_node, char reenter)
355 {
356 	Node* node = (Node*)_node;
357 // DANGER: See netfs_write_vnode().
358 //	PRINT(("netfs_remove_vnode(%p, %p, %d)\n", ns, node, reenter));
359 	status_t error = node->GetVolume()->RemoveVNode(node, reenter);
360 //	PRINT(("netfs_remove_vnode() done: %" B_PRIx32 "\n", error));
361 	return error;
362 }
363 
364 // #pragma mark -
365 // #pragma mark ----- nodes -----
366 
367 #if 0 // not used
368 
369 // netfs_fsync
370 static
371 int
372 netfs_fsync(void *ns, void *_node)
373 {
374 	Node* node = (Node*)_node;
375 	PRINT("netfs_fsync(%p, %p)\n", ns, node);
376 	status_t error = node->GetVolume()->FSync(node);
377 	PRINT("netfs_fsync() done: %" B_PRIx32 "\n", error);
378 	return error;
379 }
380 
381 #endif
382 
383 // netfs_read_stat
384 static
385 int
netfs_read_stat(void * ns,void * _node,struct stat * st)386 netfs_read_stat(void *ns, void *_node, struct stat *st)
387 {
388 	Node* node = (Node*)_node;
389 	PRINT("netfs_read_stat(%p, %p, %p)\n", ns, node, st);
390 	status_t error = node->GetVolume()->ReadStat(node, st);
391 	PRINT("netfs_read_stat() done: %" B_PRIx32 "\n", error);
392 	return error;
393 }
394 
395 // netfs_write_stat
396 static
397 int
netfs_write_stat(void * ns,void * _node,struct stat * st,long mask)398 netfs_write_stat(void *ns, void *_node, struct stat *st, long mask)
399 {
400 	Node* node = (Node*)_node;
401 	PRINT("netfs_write_stat(%p, %p, %p, %ld)\n", ns, node, st, mask);
402 	status_t error = node->GetVolume()->WriteStat(node, st, mask);
403 	PRINT("netfs_write_stat() done: %" B_PRIx32 "\n", error);
404 	return error;
405 }
406 
407 // netfs_access
408 static
409 int
netfs_access(void * ns,void * _node,int mode)410 netfs_access(void *ns, void *_node, int mode)
411 {
412 	Node* node = (Node*)_node;
413 	PRINT("netfs_access(%p, %p, %d)\n", ns, node, mode);
414 	status_t error = node->GetVolume()->Access(node, mode);
415 	PRINT("netfs_access() done: %" B_PRIx32 "\n", error);
416 	return error;
417 }
418 
419 // #pragma mark -
420 // #pragma mark ----- files -----
421 
422 // netfs_create
423 static
424 int
netfs_create(void * ns,void * _dir,const char * name,int openMode,int mode,vnode_id * vnid,void ** cookie)425 netfs_create(void *ns, void *_dir, const char *name, int openMode, int mode,
426 	vnode_id *vnid, void **cookie)
427 {
428 	Node* dir = (Node*)_dir;
429 	PRINT("netfs_create(%p, %p, `%s', %d, %d, %p, %p)\n", ns, dir,
430 		name, openMode, mode, vnid, cookie);
431 	status_t error = dir->GetVolume()->Create(dir, name, openMode, mode, vnid,
432 		cookie);
433 	PRINT("netfs_create() done: (%" B_PRIx32 ", %" B_PRIdINO ", %p)\n", error, *vnid,
434 		*cookie);
435 	return error;
436 }
437 
438 // netfs_open
439 static
440 int
netfs_open(void * ns,void * _node,int openMode,void ** cookie)441 netfs_open(void *ns, void *_node, int openMode, void **cookie)
442 {
443 	Node* node = (Node*)_node;
444 	PRINT("netfs_open(%p, %p, %d)\n", ns, node, openMode);
445 	status_t error = node->GetVolume()->Open(node, openMode, cookie);
446 	PRINT("netfs_open() done: (%" B_PRIx32 ", %p)\n", error, *cookie);
447 	return error;
448 }
449 
450 // netfs_close
451 static
452 int
netfs_close(void * ns,void * _node,void * cookie)453 netfs_close(void *ns, void *_node, void *cookie)
454 {
455 	Node* node = (Node*)_node;
456 	PRINT("netfs_close(%p, %p, %p)\n", ns, node, cookie);
457 	status_t error = node->GetVolume()->Close(node, cookie);
458 	PRINT("netfs_close() done: %" B_PRIx32 "\n", error);
459 	return error;
460 }
461 
462 // netfs_free_cookie
463 static
464 int
netfs_free_cookie(void * ns,void * _node,void * cookie)465 netfs_free_cookie(void *ns, void *_node, void *cookie)
466 {
467 	Node* node = (Node*)_node;
468 	PRINT("netfs_free_cookie(%p, %p, %p)\n", ns, node, cookie);
469 	status_t error = node->GetVolume()->FreeCookie(node, cookie);
470 	PRINT("netfs_free_cookie() done: %" B_PRIx32 "\n", error);
471 	return error;
472 }
473 
474 // netfs_read
475 static
476 int
netfs_read(void * ns,void * _node,void * cookie,off_t pos,void * buffer,size_t * bufferSize)477 netfs_read(void *ns, void *_node, void *cookie, off_t pos, void *buffer,
478 	size_t *bufferSize)
479 {
480 	Node* node = (Node*)_node;
481 	PRINT("netfs_read(%p, %p, %p, %" B_PRIdOFF ", %p, %lu)\n", ns, node,
482 		cookie, pos, buffer, *bufferSize);
483 	status_t error = node->GetVolume()->Read(node, cookie, pos, buffer,
484 		*bufferSize, bufferSize);
485 	PRINT("netfs_read() done: (%" B_PRIx32 ", %lu)\n", error, *bufferSize);
486 	return error;
487 }
488 
489 // netfs_write
490 static
491 int
netfs_write(void * ns,void * _node,void * cookie,off_t pos,const void * buffer,size_t * bufferSize)492 netfs_write(void *ns, void *_node, void *cookie, off_t pos,
493 	const void *buffer, size_t *bufferSize)
494 {
495 	Node* node = (Node*)_node;
496 	PRINT("netfs_write(%p, %p, %p, %" B_PRIdOFF ", %p, %lu)\n", ns, node,
497 		cookie, pos, buffer, *bufferSize);
498 	status_t error = node->GetVolume()->Write(node, cookie, pos, buffer,
499 		*bufferSize, bufferSize);
500 	PRINT("netfs_write() done: (%" B_PRIx32 ", %lu)\n", error, *bufferSize);
501 	return error;
502 }
503 
504 // netfs_ioctl
505 static
506 int
netfs_ioctl(void * ns,void * _node,void * cookie,int cmd,void * buffer,size_t bufferSize)507 netfs_ioctl(void *ns, void *_node, void *cookie, int cmd, void *buffer,
508 	size_t bufferSize)
509 {
510 	Node* node = (Node*)_node;
511 	PRINT("netfs_ioctl(%p, %p, %p, %d, %p, %lu)\n", ns, node, cookie, cmd,
512 		buffer, bufferSize);
513 	status_t error = node->GetVolume()->IOCtl(node, cookie, cmd, buffer,
514 		bufferSize);
515 	PRINT("netfs_ioctl() done: (%" B_PRIx32 ")\n", error);
516 	return error;
517 }
518 
519 // netfs_setflags
520 //static
521 //int
522 //netfs_setflags(void *ns, void *_node, void *cookie, int flags)
523 //{
524 //	Node* node = (Node*)_node;
525 //	PRINT(("netfs_setflags(%p, %p, %p, %d)\n", ns, node, cookie, flags));
526 //	status_t error = node->GetVolume()->SetFlags(node, cookie, flags);
527 //	PRINT(("netfs_setflags() done: (%lx)\n", error));
528 //	return error;
529 //}
530 
531 // #pragma mark -
532 // #pragma mark ----- hard links / symlinks -----
533 
534 // netfs_link
535 static
536 int
netfs_link(void * ns,void * _dir,const char * name,void * _node)537 netfs_link(void *ns, void *_dir, const char *name, void *_node)
538 {
539 	Node* dir = (Node*)_dir;
540 	Node* node = (Node*)_node;
541 	PRINT("netfs_link(%p, %p, `%s', %p)\n", ns, dir, name, node);
542 	status_t error = dir->GetVolume()->Link(dir, name, node);
543 	PRINT("netfs_link() done: (%" B_PRIx32 ")\n", error);
544 	return error;
545 }
546 
547 // netfs_unlink
548 static
549 int
netfs_unlink(void * ns,void * _dir,const char * name)550 netfs_unlink(void *ns, void *_dir, const char *name)
551 {
552 	Node* dir = (Node*)_dir;
553 	PRINT("netfs_unlink(%p, %p, `%s')\n", ns, dir, name);
554 	status_t error = dir->GetVolume()->Unlink(dir, name);
555 	PRINT("netfs_unlink() done: (%" B_PRIx32 ")\n", error);
556 	return error;
557 }
558 
559 // netfs_symlink
560 static
561 int
netfs_symlink(void * ns,void * _dir,const char * name,const char * path)562 netfs_symlink(void *ns, void *_dir, const char *name, const char *path)
563 {
564 	Node* dir = (Node*)_dir;
565 	PRINT("netfs_symlink(%p, %p, `%s', `%s')\n", ns, dir, name, path);
566 	status_t error = dir->GetVolume()->Symlink(dir, name, path);
567 	PRINT("netfs_symlink() done: (%" B_PRIx32 ")\n", error);
568 	return error;
569 }
570 
571 // netfs_read_link
572 static
573 int
netfs_read_link(void * ns,void * _node,char * buffer,size_t * bufferSize)574 netfs_read_link(void *ns, void *_node, char *buffer, size_t *bufferSize)
575 {
576 	Node* node = (Node*)_node;
577 	PRINT("netfs_read_link(%p, %p, %p, %lu)\n", ns, node, buffer,
578 		*bufferSize);
579 
580 	// TODO: If this were to be implemented (which it isn't, it currently just
581 	// returns B_BAD_VALUE) then this will need to be changed to return the
582 	// length of the node and not the number of bytes read into buffer.
583 	status_t error = node->GetVolume()->ReadLink(node, buffer, *bufferSize,
584 		bufferSize);
585 	PRINT("netfs_read_link() done: (%" B_PRIx32 ", %lu)\n", error,
586 		*bufferSize);
587 	return error;
588 }
589 
590 // netfs_rename
591 static
592 int
netfs_rename(void * ns,void * _oldDir,const char * oldName,void * _newDir,const char * newName)593 netfs_rename(void *ns, void *_oldDir, const char *oldName, void *_newDir,
594 	const char *newName)
595 {
596 	Node* oldDir = (Node*)_oldDir;
597 	Node* newDir = (Node*)_newDir;
598 	PRINT("netfs_rename(%p, %p, `%s', %p, `%s')\n", ns, oldDir, oldName,
599 		newDir, newName);
600 	status_t error = oldDir->GetVolume()->Rename(oldDir, oldName,
601 		newDir, newName);
602 	PRINT("netfs_rename() done: (%" B_PRIx32 ")\n", error);
603 	return error;
604 }
605 
606 // #pragma mark -
607 // #pragma mark ----- directories -----
608 
609 // netfs_mkdir
610 static
611 int
netfs_mkdir(void * ns,void * _dir,const char * name,int mode)612 netfs_mkdir(void *ns, void *_dir, const char *name, int mode)
613 {
614 	Node* dir = (Node*)_dir;
615 	PRINT("netfs_mkdir(%p, %p, `%s', %d)\n", ns, dir, name, mode);
616 	status_t error = dir->GetVolume()->MkDir(dir, name, mode);
617 	PRINT("netfs_mkdir() done: (%" B_PRIx32 ")\n", error);
618 	return error;
619 }
620 
621 // netfs_rmdir
622 static
623 int
netfs_rmdir(void * ns,void * _dir,const char * name)624 netfs_rmdir(void *ns, void *_dir, const char *name)
625 {
626 	Node* dir = (Node*)_dir;
627 	PRINT("netfs_rmdir(%p, %p, `%s')\n", ns, dir, name);
628 	status_t error = dir->GetVolume()->RmDir(dir, name);
629 	PRINT("netfs_rmdir() done: (%" B_PRIx32 ")\n", error);
630 	return error;
631 }
632 
633 // netfs_open_dir
634 static
635 int
netfs_open_dir(void * ns,void * _node,void ** cookie)636 netfs_open_dir(void *ns, void *_node, void **cookie)
637 {
638 	Node* node = (Node*)_node;
639 	PRINT("netfs_open_dir(%p, %p)\n", ns, node);
640 	status_t error = node->GetVolume()->OpenDir(node, cookie);
641 	PRINT("netfs_open_dir() done: (%" B_PRIx32 ", %p)\n", error, *cookie);
642 	return error;
643 }
644 
645 // netfs_close_dir
646 static
647 int
netfs_close_dir(void * ns,void * _node,void * cookie)648 netfs_close_dir(void *ns, void *_node, void *cookie)
649 {
650 	Node* node = (Node*)_node;
651 	PRINT("netfs_close_dir(%p, %p, %p)\n", ns, node, cookie);
652 	status_t error = node->GetVolume()->CloseDir(node, cookie);
653 	PRINT("netfs_close_dir() done: %" B_PRIx32 "\n", error);
654 	return error;
655 }
656 
657 // netfs_free_dir_cookie
658 static
659 int
netfs_free_dir_cookie(void * ns,void * _node,void * cookie)660 netfs_free_dir_cookie(void *ns, void *_node, void *cookie)
661 {
662 	Node* node = (Node*)_node;
663 	PRINT("netfs_free_dir_cookie(%p, %p, %p)\n", ns, node, cookie);
664 	status_t error = node->GetVolume()->FreeDirCookie(node, cookie);
665 	PRINT("netfs_free_dir_cookie() done: %" B_PRIx32 " \n", error);
666 	return error;
667 }
668 
669 // netfs_read_dir
670 static
671 int
netfs_read_dir(void * ns,void * _node,void * cookie,long * count,struct dirent * buffer,size_t bufferSize)672 netfs_read_dir(void *ns, void *_node, void *cookie, long *count,
673 	struct dirent *buffer, size_t bufferSize)
674 {
675 	Node* node = (Node*)_node;
676 	PRINT("netfs_read_dir(%p, %p, %p, %ld, %p, %lu)\n", ns, node, cookie,
677 		*count, buffer, bufferSize);
678 	int32 _count = *count;
679 	status_t error = node->GetVolume()->ReadDir(node, cookie, buffer,
680 		bufferSize, _count, &_count);
681 	*count = _count;
682 	PRINT("netfs_read_dir() done: (%" B_PRIx32 ", %ld)\n", error, *count);
683 	#if DEBUG
684 		dirent* entry = buffer;
685 		for (int32 i = 0; i < *count; i++) {
686 			// R5's kernel vsprintf() doesn't seem to know `%.<number>s', so
687 			// we need to work around.
688 			char name[B_FILE_NAME_LENGTH];
689 			int nameLen = strnlen(entry->d_name, B_FILE_NAME_LENGTH - 1);
690 			strncpy(name, entry->d_name, nameLen);
691 			name[nameLen] = '\0';
692 			PRINT("  entry: d_dev: %" B_PRIdDEV ", d_pdev: %" B_PRIdDEV
693 				", d_ino: %" B_PRIdINO ", d_pino: %" B_PRIdINO
694 				", d_reclen: %hu, d_name: `%s'\n",
695 				entry->d_dev, entry->d_pdev, entry->d_ino,
696 				entry->d_pino, entry->d_reclen, name);
697 			entry = (dirent*)((char*)entry + entry->d_reclen);
698 		}
699 	#endif
700 
701 	return error;
702 }
703 
704 // netfs_rewind_dir
705 static
706 int
netfs_rewind_dir(void * ns,void * _node,void * cookie)707 netfs_rewind_dir(void *ns, void *_node, void *cookie)
708 {
709 	Node* node = (Node*)_node;
710 	PRINT("netfs_rewind_dir(%p, %p, %p)\n", ns, node, cookie);
711 	status_t error = node->GetVolume()->RewindDir(node, cookie);
712 	PRINT("netfs_rewind_dir() done: %" B_PRIx32 "\n", error);
713 	return error;
714 }
715 
716 // netfs_walk
717 static
718 int
netfs_walk(void * ns,void * _dir,const char * entryName,char ** resolvedPath,vnode_id * vnid)719 netfs_walk(void *ns, void *_dir, const char *entryName,
720 	char **resolvedPath, vnode_id *vnid)
721 {
722 	Node* dir = (Node*)_dir;
723 	PRINT("netfs_walk(%p, %p, `%s', %p, %p)\n", ns, dir,
724 		entryName, resolvedPath, vnid);
725 	status_t error = dir->GetVolume()->Walk(dir, entryName, resolvedPath, vnid);
726 	PRINT("netfs_walk() done: (%" B_PRIx32 ", `%s', %" B_PRIdINO ")\n", error,
727 		(resolvedPath ? *resolvedPath : NULL), *vnid);
728 	return error;
729 }
730 
731 // #pragma mark -
732 // #pragma mark ----- attributes -----
733 
734 // netfs_open_attrdir
735 static
736 int
netfs_open_attrdir(void * ns,void * _node,void ** cookie)737 netfs_open_attrdir(void *ns, void *_node, void **cookie)
738 {
739 	Node* node = (Node*)_node;
740 	PRINT("netfs_open_attrdir(%p, %p)\n", ns, node);
741 	status_t error = node->GetVolume()->OpenAttrDir(node, cookie);
742 	PRINT("netfs_open_attrdir() done: (%" B_PRIx32 ", %p)\n", error, *cookie);
743 	return error;
744 }
745 
746 // netfs_close_attrdir
747 static
748 int
netfs_close_attrdir(void * ns,void * _node,void * cookie)749 netfs_close_attrdir(void *ns, void *_node, void *cookie)
750 {
751 	Node* node = (Node*)_node;
752 	PRINT("netfs_close_attrdir(%p, %p, %p)\n", ns, node, cookie);
753 	status_t error = node->GetVolume()->CloseAttrDir(node, cookie);
754 	PRINT("netfs_close_attrdir() done: (%" B_PRIx32 ")\n", error);
755 	return error;
756 }
757 
758 // netfs_free_attrdir_cookie
759 static
760 int
netfs_free_attrdir_cookie(void * ns,void * _node,void * cookie)761 netfs_free_attrdir_cookie(void *ns, void *_node, void *cookie)
762 {
763 	Node* node = (Node*)_node;
764 	PRINT("netfs_free_attrdir_cookie(%p, %p, %p)\n", ns, node, cookie);
765 	status_t error = node->GetVolume()->FreeAttrDirCookie(node, cookie);
766 	PRINT("netfs_free_attrdir_cookie() done: (%" B_PRIx32 ")\n", error);
767 	return error;
768 }
769 
770 // netfs_read_attrdir
771 static
772 int
netfs_read_attrdir(void * ns,void * _node,void * cookie,long * count,struct dirent * buffer,size_t bufferSize)773 netfs_read_attrdir(void *ns, void *_node, void *cookie, long *count,
774 	struct dirent *buffer, size_t bufferSize)
775 {
776 	Node* node = (Node*)_node;
777 	PRINT("netfs_read_attrdir(%p, %p, %p, %ld, %p, %lu)\n", ns, node,
778 		cookie, *count, buffer, bufferSize);
779 	int32 _count = *count;
780 	status_t error = node->GetVolume()->ReadAttrDir(node, cookie, buffer,
781 		bufferSize, _count, &_count);
782 	*count = _count;
783 	PRINT("netfs_read_attrdir() done: (%" B_PRIx32 ", %ld)\n", error, *count);
784 	return error;
785 }
786 
787 // netfs_rewind_attrdir
788 static
789 int
netfs_rewind_attrdir(void * ns,void * _node,void * cookie)790 netfs_rewind_attrdir(void *ns, void *_node, void *cookie)
791 {
792 	Node* node = (Node*)_node;
793 	PRINT("netfs_rewind_attrdir(%p, %p, %p)\n", ns, node, cookie);
794 	status_t error = node->GetVolume()->RewindAttrDir(node, cookie);
795 	PRINT("netfs_rewind_attrdir() done: (%" B_PRIx32 ")\n", error);
796 	return error;
797 }
798 
799 // netfs_read_attr
800 static
801 int
netfs_read_attr(void * ns,void * _node,const char * name,int type,void * buffer,size_t * bufferSize,off_t pos)802 netfs_read_attr(void *ns, void *_node, const char *name, int type,
803 	void *buffer, size_t *bufferSize, off_t pos)
804 {
805 	Node* node = (Node*)_node;
806 	PRINT("netfs_read_attr(%p, %p, `%s', %d, %p, %lu, %" B_PRIdOFF ")\n", ns,
807 		node, name, type, buffer, *bufferSize, pos);
808 	status_t error = node->GetVolume()->ReadAttr(node, name, type, pos, buffer,
809 		*bufferSize, bufferSize);
810 	PRINT("netfs_read_attr() done: (%" B_PRIx32 ", %ld)\n", error,
811 		*bufferSize);
812 	return error;
813 }
814 
815 // netfs_write_attr
816 static
817 int
netfs_write_attr(void * ns,void * _node,const char * name,int type,const void * buffer,size_t * bufferSize,off_t pos)818 netfs_write_attr(void *ns, void *_node, const char *name, int type,
819 	const void *buffer, size_t *bufferSize, off_t pos)
820 {
821 	Node* node = (Node*)_node;
822 	PRINT("netfs_write_attr(%p, %p, `%s', %d, %p, %lu, %" B_PRIdOFF ")\n", ns,
823 		node, name, type, buffer, *bufferSize, pos);
824 	status_t error = node->GetVolume()->WriteAttr(node, name, type, pos, buffer,
825 		*bufferSize, bufferSize);
826 	PRINT("netfs_write_attr() done: (%" B_PRIx32 ", %ld)\n", error,
827 		*bufferSize);
828 	return error;
829 }
830 
831 // netfs_remove_attr
832 static
833 int
netfs_remove_attr(void * ns,void * _node,const char * name)834 netfs_remove_attr(void *ns, void *_node, const char *name)
835 {
836 	Node* node = (Node*)_node;
837 	PRINT("netfs_remove_attr(%p, %p, `%s')\n", ns, node, name);
838 	status_t error = node->GetVolume()->RemoveAttr(node, name);
839 	PRINT("netfs_remove_attr() done: (%" B_PRIx32 ")\n", error);
840 	return error;
841 }
842 
843 // netfs_rename_attr
844 static
845 int
netfs_rename_attr(void * ns,void * _node,const char * oldName,const char * newName)846 netfs_rename_attr(void *ns, void *_node, const char *oldName,
847 	const char *newName)
848 {
849 	Node* node = (Node*)_node;
850 	PRINT("netfs_rename_attr(%p, %p, `%s', `%s')\n", ns, node, oldName,
851 		newName);
852 	status_t error = node->GetVolume()->RenameAttr(node, oldName, newName);
853 	PRINT("netfs_rename_attr() done: (%" B_PRIx32 ")\n", error);
854 	return error;
855 }
856 
857 // netfs_stat_attr
858 static
859 int
netfs_stat_attr(void * ns,void * _node,const char * name,struct attr_info * attrInfo)860 netfs_stat_attr(void *ns, void *_node, const char *name,
861 	struct attr_info *attrInfo)
862 {
863 	Node* node = (Node*)_node;
864 	PRINT("netfs_stat_attr(%p, %p, `%s', %p)\n", ns, node, name,
865 		attrInfo);
866 	status_t error = node->GetVolume()->StatAttr(node, name, attrInfo);
867 	PRINT("netfs_stat_attr() done: (%" B_PRIx32 ")\n", error);
868 	return error;
869 }
870 
871 // #pragma mark -
872 // #pragma mark ----- queries -----
873 
874 // netfs_open_query
875 static
876 int
netfs_open_query(void * ns,const char * queryString,ulong flags,port_id port,long token,void ** cookie)877 netfs_open_query(void *ns, const char *queryString, ulong flags,
878 	port_id port, long token, void **cookie)
879 {
880 	VolumeManager* volumeManager = (VolumeManager*)ns;
881 	Volume* volume = volumeManager->GetRootVolume();
882 	VolumePutter _(volume);
883 
884 	PRINT("netfs_open_query(%p, `%s', %lu, %" B_PRId32 ", %ld, %p)\n", ns,
885 		queryString, flags, port, token, cookie);
886 
887 	status_t error = B_BAD_VALUE;
888 	if (volume) {
889 		error = volume->OpenQuery(queryString, flags, port, token,
890 			(QueryIterator**)cookie);
891 	}
892 
893 	PRINT("netfs_open_query() done: (%" B_PRIx32 ", %p)\n", error, *cookie);
894 	return error;
895 }
896 
897 // netfs_close_query
898 static
899 int
netfs_close_query(void * ns,void * cookie)900 netfs_close_query(void *ns, void *cookie)
901 {
902 	PRINT("netfs_close_query(%p, %p)\n", ns, cookie);
903 
904 	status_t error = B_OK;
905 	// no-op: we don't use this hook
906 
907 	PRINT("netfs_close_query() done: (%" B_PRIx32 ")\n", error);
908 	return error;
909 }
910 
911 // netfs_free_query_cookie
912 static
913 int
netfs_free_query_cookie(void * ns,void * node,void * cookie)914 netfs_free_query_cookie(void *ns, void *node, void *cookie)
915 {
916 	VolumeManager* volumeManager = (VolumeManager*)ns;
917 	QueryIterator* iterator = (QueryIterator*)cookie;
918 
919 	PRINT("netfs_free_query_cookie(%p, %p)\n", ns, cookie);
920 
921 	status_t error = B_OK;
922 	volumeManager->GetQueryManager()->PutIterator(iterator);
923 
924 	PRINT("netfs_free_query_cookie() done: (%" B_PRIx32 ")\n", error);
925 	return error;
926 }
927 
928 // netfs_read_query
929 static
930 int
netfs_read_query(void * ns,void * cookie,long * count,struct dirent * buffer,size_t bufferSize)931 netfs_read_query(void *ns, void *cookie, long *count,
932 	struct dirent *buffer, size_t bufferSize)
933 {
934 	VolumeManager* volumeManager = (VolumeManager*)ns;
935 	Volume* volume = volumeManager->GetRootVolume();
936 	QueryIterator* iterator = (QueryIterator*)cookie;
937 	VolumePutter _(volume);
938 
939 	PRINT("netfs_read_query(%p, %p, %ld, %p, %lu)\n", ns, cookie,
940 		*count, buffer, bufferSize);
941 
942 	status_t error = B_BAD_VALUE;
943 	if (volume) {
944 		int32 _count = *count;
945 		error = volume->ReadQuery(iterator, buffer, bufferSize,
946 			_count, &_count);
947 		*count = _count;
948 	}
949 
950 	PRINT("netfs_read_query() done: (%" B_PRIx32 ", %ld)\n", error, *count);
951 	return error;
952 }
953 
954