1// kernel_interface.cpp
2
3#include <KernelExport.h>
4#include <fsproto.h>
5
6#include "Debug.h"
7#include "FileSystem.h"
8#include "String.h"
9#include "UserlandFS.h"
10#include "Volume.h"
11
12#if USER
13
14// disable_interrupts
15static inline
16cpu_status
17disable_interrupts()
18{
19	return 0;
20}
21
22// restore_interrupts
23static inline
24void
25restore_interrupts(cpu_status status)
26{
27}
28
29#endif	// USER
30
31// #pragma mark -
32// #pragma mark ----- prototypes -----
33
34extern "C" {
35
36// fs
37static int userlandfs_mount(nspace_id nsid, const char *device, ulong flags,
38				void *parameters, size_t len, void **data, vnode_id *rootID);
39static int userlandfs_unmount(void *ns);
40static int userlandfs_initialize(const char *deviceName, void *parameters,
41				size_t len);
42static int userlandfs_sync(void *ns);
43static int userlandfs_read_fs_stat(void *ns, struct fs_info *info);
44static int userlandfs_write_fs_stat(void *ns, struct fs_info *info, long mask);
45
46// vnodes
47static int userlandfs_read_vnode(void *ns, vnode_id vnid, char reenter,
48				void **node);
49static int userlandfs_write_vnode(void *ns, void *node, char reenter);
50static int userlandfs_remove_vnode(void *ns, void *node, char reenter);
51
52// nodes
53static int userlandfs_fsync(void *ns, void *node);
54static int userlandfs_read_stat(void *ns, void *node, struct stat *st);
55static int userlandfs_write_stat(void *ns, void *node, struct stat *st,
56				long mask);
57static int userlandfs_access(void *ns, void *node, int mode);
58
59// files
60static int userlandfs_create(void *ns, void *dir, const char *name,
61				int openMode, int mode, vnode_id *vnid, void **cookie);
62static int userlandfs_open(void *ns, void *node, int openMode, void **cookie);
63static int userlandfs_close(void *ns, void *node, void *cookie);
64static int userlandfs_free_cookie(void *ns, void *node, void *cookie);
65static int userlandfs_read(void *ns, void *node, void *cookie, off_t pos,
66				void *buffer, size_t *bufferSize);
67static int userlandfs_write(void *ns, void *node, void *cookie, off_t pos,
68				const void *buffer, size_t *bufferSize);
69static int userlandfs_ioctl(void *ns, void *node, void *cookie, int cmd,
70				void *buffer, size_t bufferSize);
71static int userlandfs_setflags(void *ns, void *node, void *cookie, int flags);
72static int userlandfs_select(void *ns, void *node, void *cookie, uint8 event,
73				uint32 ref, selectsync *sync);
74static int userlandfs_deselect(void *ns, void *node, void *cookie, uint8 event,
75				selectsync *sync);
76
77// hard links / symlinks
78static int userlandfs_link(void *ns, void *dir, const char *name, void *node);
79static int userlandfs_unlink(void *ns, void *dir, const char *name);
80static int userlandfs_symlink(void *ns, void *dir, const char *name,
81				const char *path);
82static int userlandfs_read_link(void *ns, void *node, char *buffer,
83				size_t *bufferSize);
84static int userlandfs_rename(void *ns, void *oldDir, const char *oldName,
85				void *newDir, const char *newName);
86
87// directories
88static int userlandfs_mkdir(void *ns, void *dir, const char *name, int mode);
89static int userlandfs_rmdir(void *ns, void *dir, const char *name);
90static int userlandfs_open_dir(void *ns, void *node, void **cookie);
91static int userlandfs_close_dir(void *ns, void *node, void *cookie);
92static int userlandfs_free_dir_cookie(void *ns, void *node, void *cookie);
93static int userlandfs_read_dir(void *ns, void *node, void *cookie,
94				long *count, struct dirent *buffer, size_t bufferSize);
95static int userlandfs_rewind_dir(void *ns, void *node, void *cookie);
96static int userlandfs_walk(void *ns, void *dir, const char *entryName,
97				char **resolvedPath, vnode_id *vnid);
98
99// attributes
100static int userlandfs_open_attrdir(void *ns, void *node, void **cookie);
101static int userlandfs_close_attrdir(void *ns, void *node, void *cookie);
102static int userlandfs_free_attrdir_cookie(void *ns, void *node, void *cookie);
103static int userlandfs_read_attrdir(void *ns, void *node, void *cookie,
104				long *count, struct dirent *buffer, size_t bufferSize);
105static int userlandfs_read_attr(void *ns, void *node, const char *name,
106				int type, void *buffer, size_t *bufferSize, off_t pos);
107static int userlandfs_rewind_attrdir(void *ns, void *node, void *cookie);
108static int userlandfs_write_attr(void *ns, void *node, const char *name,
109				int type, const void *buffer, size_t *bufferSize, off_t pos);
110static int userlandfs_remove_attr(void *ns, void *node, const char *name);
111static int userlandfs_rename_attr(void *ns, void *node, const char *oldName,
112				const char *newName);
113static int userlandfs_stat_attr(void *ns, void *node, const char *name,
114				struct attr_info *attrInfo);
115
116// indices
117static int userlandfs_open_indexdir(void *ns, void **cookie);
118static int userlandfs_close_indexdir(void *ns, void *cookie);
119static int userlandfs_free_indexdir_cookie(void *ns, void *node, void *cookie);
120static int userlandfs_read_indexdir(void *ns, void *cookie, long *count,
121				struct dirent *buffer, size_t bufferSize);
122static int userlandfs_rewind_indexdir(void *ns, void *cookie);
123static int userlandfs_create_index(void *ns, const char *name, int type, int flags);
124static int userlandfs_remove_index(void *ns, const char *name);
125static int userlandfs_rename_index(void *ns, const char *oldName,
126				const char *newName);
127static int userlandfs_stat_index(void *ns, const char *name,
128				struct index_info *indexInfo);
129
130// queries
131static int userlandfs_open_query(void *ns, const char *queryString, ulong flags,
132				port_id port, long token, void **cookie);
133static int userlandfs_close_query(void *ns, void *cookie);
134static int userlandfs_free_query_cookie(void *ns, void *node, void *cookie);
135static int userlandfs_read_query(void *ns, void *cookie, long *count,
136				struct dirent *buffer, size_t bufferSize);
137
138} // extern "C"
139
140/* vnode_ops struct. Fill this in to tell the kernel how to call
141	functions in your driver.
142*/
143vnode_ops fs_entry =  {
144	&userlandfs_read_vnode,			// read_vnode
145	&userlandfs_write_vnode,		// write_vnode
146	&userlandfs_remove_vnode,		// remove_vnode
147	NULL,							// secure_vnode (not needed)
148	&userlandfs_walk,				// walk
149	&userlandfs_access,				// access
150	&userlandfs_create,				// create
151	&userlandfs_mkdir,				// mkdir
152	&userlandfs_symlink,			// symlink
153	&userlandfs_link,				// link
154	&userlandfs_rename,				// rename
155	&userlandfs_unlink,				// unlink
156	&userlandfs_rmdir,				// rmdir
157	&userlandfs_read_link,			// readlink
158	&userlandfs_open_dir,			// opendir
159	&userlandfs_close_dir,			// closedir
160	&userlandfs_free_dir_cookie,	// free_dircookie
161	&userlandfs_rewind_dir,			// rewinddir
162	&userlandfs_read_dir,			// readdir
163	&userlandfs_open,				// open file
164	&userlandfs_close,				// close file
165	&userlandfs_free_cookie,		// free cookie
166	&userlandfs_read,				// read file
167	&userlandfs_write,				// write file
168	NULL,							// readv
169	NULL,							// writev
170	&userlandfs_ioctl,				// ioctl
171	&userlandfs_setflags,			// setflags file
172	&userlandfs_read_stat,			// read stat
173	&userlandfs_write_stat,			// write stat
174	&userlandfs_fsync,				// fsync
175	&userlandfs_initialize,			// initialize
176	&userlandfs_mount,				// mount
177	&userlandfs_unmount,			// unmount
178	&userlandfs_sync,				// sync
179	&userlandfs_read_fs_stat,		// read fs stat
180	&userlandfs_write_fs_stat,		// write fs stat
181	&userlandfs_select,				// select
182	&userlandfs_deselect,			// deselect
183
184	&userlandfs_open_indexdir,		// open index dir
185	&userlandfs_close_indexdir,		// close index dir
186	&userlandfs_free_indexdir_cookie,	// free index dir cookie
187	&userlandfs_rewind_indexdir,	// rewind index dir
188	&userlandfs_read_indexdir,		// read index dir
189	&userlandfs_create_index,		// create index
190	&userlandfs_remove_index,		// remove index
191	&userlandfs_rename_index,		// rename index
192	&userlandfs_stat_index,			// stat index
193
194	&userlandfs_open_attrdir,		// open attr dir
195	&userlandfs_close_attrdir,		// close attr dir
196	&userlandfs_free_attrdir_cookie,	// free attr dir cookie
197	&userlandfs_rewind_attrdir,		// rewind attr dir
198	&userlandfs_read_attrdir,		// read attr dir
199	&userlandfs_write_attr,			// write attr
200	&userlandfs_read_attr,			// read attr
201	&userlandfs_remove_attr,		// remove attr
202	&userlandfs_rename_attr,		// rename attr
203	&userlandfs_stat_attr,			// stat attr
204
205	&userlandfs_open_query,			// open query
206	&userlandfs_close_query,		// close query
207	&userlandfs_free_query_cookie,	// free query cookie
208	&userlandfs_read_query,			// read query
209};
210
211int32 api_version = B_CUR_FS_API_VERSION;
212
213// #pragma mark -
214// #pragma mark ----- fs -----
215
216// parse_parameters
217static
218status_t
219parse_parameters(const void *_parameters, int32 _len, String &fsName,
220	const char **fsParameters, int32 *fsParameterLength)
221{
222	// check parameters
223	if (!_parameters || _len <= 0)
224		return B_BAD_VALUE;
225	const char* parameters = (const char*)_parameters;
226	int32 len = strnlen(parameters, _len);
227	// skip leading white space
228	for (; len > 0; parameters++, len--) {
229		if (*parameters != ' ' && *parameters != '\t' && *parameters != '\n')
230			break;
231	}
232	if (len == 0)
233		return B_BAD_VALUE;
234	// get the file system name
235	int32 fsNameLen = len;
236	for (int32 i = 0; i < len; i++) {
237		if (parameters[i] == ' ' || parameters[i] == '\t'
238			|| parameters[i] == '\n') {
239			fsNameLen = i;
240			break;
241		}
242	}
243	fsName.SetTo(parameters, fsNameLen);
244	if (fsName.GetLength() == 0) {
245		exit_debugging();
246		return B_NO_MEMORY;
247	}
248	parameters += fsNameLen;
249	len -= fsNameLen;
250	// skip leading white space of the FS parameters
251	for (; len > 0; parameters++, len--) {
252		if (*parameters != ' ' && *parameters != '\t' && *parameters != '\n')
253			break;
254	}
255	*fsParameters = parameters;
256	*fsParameterLength = len;
257	return B_OK;
258}
259
260// userlandfs_mount
261static
262int
263userlandfs_mount(nspace_id nsid, const char *device, ulong flags,
264	void *parameters, size_t len, void **data, vnode_id *rootID)
265{
266	status_t error = B_OK;
267	init_debugging();
268	// get the parameters
269	String fsName;
270	const char* fsParameters;
271	int32 fsParameterLength;
272	error = parse_parameters(parameters, len, fsName, &fsParameters,
273		&fsParameterLength);
274	if (error != B_OK) {
275		exit_debugging();
276		return error;
277	}
278	// make sure there is a UserlandFS we can work with
279	UserlandFS* userlandFS = NULL;
280	error = UserlandFS::RegisterUserlandFS(&userlandFS);
281	if (error != B_OK) {
282		exit_debugging();
283		return error;
284	}
285	// get the file system
286	FileSystem* fileSystem = NULL;
287	error = userlandFS->RegisterFileSystem(fsName.GetString(), &fileSystem);
288	if (error != B_OK) {
289		UserlandFS::UnregisterUserlandFS();
290		exit_debugging();
291		return error;
292	}
293	// mount the volume
294	Volume* volume = NULL;
295	error = fileSystem->Mount(nsid, device, flags, fsParameters,
296		fsParameterLength, &volume);
297	if (error != B_OK) {
298		userlandFS->UnregisterFileSystem(fileSystem);
299		UserlandFS::UnregisterUserlandFS();
300		exit_debugging();
301		return error;
302	}
303	*data = volume;
304	*rootID = volume->GetRootID();
305	return error;
306}
307
308// userlandfs_unmount
309static
310int
311userlandfs_unmount(void *ns)
312{
313	Volume* volume = (Volume*)ns;
314	FileSystem* fileSystem = volume->GetFileSystem();
315	status_t error = volume->Unmount();
316	// The error code the FS's unmount hook returns is completely irrelevant to
317	// the VFS. It considers the volume unmounted in any case.
318	volume->RemoveReference();
319	UserlandFS::GetUserlandFS()->UnregisterFileSystem(fileSystem);
320	UserlandFS::UnregisterUserlandFS();
321	exit_debugging();
322	return error;
323}
324
325// userlandfs_initialize
326static
327int
328userlandfs_initialize(const char *deviceName, void *parameters,
329	size_t len)
330{
331	init_debugging();
332	// get the parameters
333	String fsName;
334	const char* fsParameters;
335	int32 fsParameterLength;
336	status_t error = parse_parameters(parameters, len, fsName, &fsParameters,
337		&fsParameterLength);
338	// make sure there is a UserlandFS we can work with
339	UserlandFS* userlandFS = NULL;
340	error = UserlandFS::RegisterUserlandFS(&userlandFS);
341	if (error != B_OK) {
342		exit_debugging();
343		return error;
344	}
345	// get the file system
346	FileSystem* fileSystem = NULL;
347	if (error == B_OK)
348		error = userlandFS->RegisterFileSystem(fsName.GetString(), &fileSystem);
349	// initialize the volume
350	if (error == B_OK) {
351		error = fileSystem->Initialize(deviceName, fsParameters,
352			fsParameterLength);
353	}
354	// cleanup
355	if (fileSystem)
356		userlandFS->UnregisterFileSystem(fileSystem);
357	UserlandFS::UnregisterUserlandFS();
358	exit_debugging();
359	return error;
360}
361
362// userlandfs_sync
363static
364int
365userlandfs_sync(void *ns)
366{
367	Volume* volume = (Volume*)ns;
368	PRINT(("userlandfs_sync(%p)\n", ns));
369	status_t error = volume->Sync();
370	PRINT(("userlandfs_sync() done: %lx \n", error));
371	return error;
372}
373
374// userlandfs_read_fs_stat
375static
376int
377userlandfs_read_fs_stat(void *ns, struct fs_info *info)
378{
379	Volume* volume = (Volume*)ns;
380	PRINT(("userlandfs_read_fs_stat(%p, %p)\n", ns, info));
381	status_t error = volume->ReadFSStat(info);
382	PRINT(("userlandfs_read_fs_stat() done: %lx \n", error));
383	return error;
384}
385
386// userlandfs_write_fs_stat
387static
388int
389userlandfs_write_fs_stat(void *ns, struct fs_info *info, long mask)
390{
391	Volume* volume = (Volume*)ns;
392	PRINT(("userlandfs_write_fs_stat(%p, %p, %ld)\n", ns, info, mask));
393	status_t error = volume->WriteFSStat(info, mask);
394	PRINT(("userlandfs_write_fs_stat() done: %lx \n", error));
395	return error;
396}
397
398// #pragma mark -
399// #pragma mark ----- vnodes -----
400
401// userlandfs_read_vnode
402static
403int
404userlandfs_read_vnode(void *ns, vnode_id vnid, char reenter, void **node)
405{
406	Volume* volume = (Volume*)ns;
407	PRINT(("userlandfs_read_vnode(%p, %Ld, %d, %p)\n", ns, vnid, reenter,
408		node));
409	status_t error = volume->ReadVNode(vnid, reenter, node);
410	PRINT(("userlandfs_read_vnode() done: (%lx, %p)\n", error, *node));
411	return error;
412}
413
414// userlandfs_write_vnode
415static
416int
417userlandfs_write_vnode(void *ns, void *node, char reenter)
418{
419	Volume* volume = (Volume*)ns;
420// DANGER: If dbg_printf() is used, this thread will enter another FS and
421// even perform a write operation. The is dangerous here, since this hook
422// may be called out of the other FSs, since, for instance a put_vnode()
423// called from another FS may cause the VFS layer to free vnodes and thus
424// invoke this hook.
425//	PRINT(("userlandfs_write_vnode(%p, %p, %d)\n", ns, node, reenter));
426	status_t error = volume->WriteVNode(node, reenter);
427//	PRINT(("userlandfs_write_vnode() done: %lx\n", error));
428	return error;
429}
430
431// userlandfs_remove_vnode
432static
433int
434userlandfs_remove_vnode(void *ns, void *node, char reenter)
435{
436	Volume* volume = (Volume*)ns;
437// DANGER: See userlandfs_write_vnode().
438//	PRINT(("userlandfs_remove_vnode(%p, %p, %d)\n", ns, node, reenter));
439	status_t error = volume->RemoveVNode(node, reenter);
440//	PRINT(("userlandfs_remove_vnode() done: %lx\n", error));
441	return error;
442}
443
444// #pragma mark -
445// #pragma mark ----- nodes -----
446
447// userlandfs_fsync
448static
449int
450userlandfs_fsync(void *ns, void *node)
451{
452	Volume* volume = (Volume*)ns;
453	PRINT(("userlandfs_fsync(%p, %p)\n", ns, node));
454	status_t error = volume->FSync(node);
455	PRINT(("userlandfs_fsync() done: %lx\n", error));
456	return error;
457}
458
459// userlandfs_read_stat
460static
461int
462userlandfs_read_stat(void *ns, void *node, struct stat *st)
463{
464	Volume* volume = (Volume*)ns;
465	PRINT(("userlandfs_read_stat(%p, %p, %p)\n", ns, node, st));
466	status_t error = volume->ReadStat(node, st);
467	PRINT(("userlandfs_read_stat() done: %lx\n", error));
468	return error;
469}
470
471// userlandfs_write_stat
472static
473int
474userlandfs_write_stat(void *ns, void *node, struct stat *st, long mask)
475{
476	Volume* volume = (Volume*)ns;
477	PRINT(("userlandfs_write_stat(%p, %p, %p, %ld)\n", ns, node, st, mask));
478	status_t error = volume->WriteStat(node, st, mask);
479	PRINT(("userlandfs_write_stat() done: %lx\n", error));
480	return error;
481}
482
483// userlandfs_access
484static
485int
486userlandfs_access(void *ns, void *node, int mode)
487{
488	Volume* volume = (Volume*)ns;
489	PRINT(("userlandfs_access(%p, %p, %d)\n", ns, node, mode));
490	status_t error = volume->Access(node, mode);
491	PRINT(("userlandfs_access() done: %lx\n", error));
492	return error;
493}
494
495// #pragma mark -
496// #pragma mark ----- files -----
497
498// userlandfs_create
499static
500int
501userlandfs_create(void *ns, void *dir, const char *name, int openMode, int mode,
502	vnode_id *vnid, void **cookie)
503{
504	Volume* volume = (Volume*)ns;
505	PRINT(("userlandfs_create(%p, %p, `%s', %d, %d, %p, %p)\n", ns, dir,
506		name, openMode, mode, vnid, cookie));
507	status_t error = volume->Create(dir, name, openMode, mode, vnid, cookie);
508	PRINT(("userlandfs_create() done: (%lx, %Ld, %p)\n", error, *vnid,
509		*cookie));
510	return error;
511}
512
513// userlandfs_open
514static
515int
516userlandfs_open(void *ns, void *node, int openMode, void **cookie)
517{
518	Volume* volume = (Volume*)ns;
519	PRINT(("userlandfs_open(%p, %p, %d)\n", ns, node, openMode));
520	status_t error = volume->Open(node, openMode, cookie);
521	PRINT(("userlandfs_open() done: (%lx, %p)\n", error, *cookie));
522	return error;
523}
524
525// userlandfs_close
526static
527int
528userlandfs_close(void *ns, void *node, void *cookie)
529{
530	Volume* volume = (Volume*)ns;
531	PRINT(("userlandfs_close(%p, %p, %p)\n", ns, node, cookie));
532	status_t error = volume->Close(node, cookie);
533	PRINT(("userlandfs_close() done: %lx\n", error));
534	return error;
535}
536
537// userlandfs_free_cookie
538static
539int
540userlandfs_free_cookie(void *ns, void *node, void *cookie)
541{
542	Volume* volume = (Volume*)ns;
543	PRINT(("userlandfs_free_cookie(%p, %p, %p)\n", ns, node, cookie));
544	status_t error = volume->FreeCookie(node, cookie);
545	PRINT(("userlandfs_free_cookie() done: %lx\n", error));
546	return error;
547}
548
549// userlandfs_read
550static
551int
552userlandfs_read(void *ns, void *node, void *cookie, off_t pos, void *buffer,
553	size_t *bufferSize)
554{
555	Volume* volume = (Volume*)ns;
556	PRINT(("userlandfs_read(%p, %p, %p, %Ld, %p, %lu)\n", ns, node, cookie, pos,
557		buffer, *bufferSize));
558	status_t error = volume->Read(node, cookie, pos, buffer, *bufferSize,
559		bufferSize);
560	PRINT(("userlandfs_read() done: (%lx, %lu)\n", error, *bufferSize));
561	return error;
562}
563
564// userlandfs_write
565static
566int
567userlandfs_write(void *ns, void *node, void *cookie, off_t pos,
568	const void *buffer, size_t *bufferSize)
569{
570	Volume* volume = (Volume*)ns;
571	PRINT(("userlandfs_write(%p, %p, %p, %Ld, %p, %lu)\n", ns, node, cookie, pos,
572		buffer, *bufferSize));
573	status_t error = volume->Write(node, cookie, pos, buffer, *bufferSize,
574		bufferSize);
575	PRINT(("userlandfs_write() done: (%lx, %lu)\n", error, *bufferSize));
576	return error;
577}
578
579// userlandfs_ioctl
580static
581int
582userlandfs_ioctl(void *ns, void *node, void *cookie, int cmd, void *buffer,
583	size_t bufferSize)
584{
585	Volume* volume = (Volume*)ns;
586	PRINT(("userlandfs_ioctl(%p, %p, %p, %d, %p, %lu)\n", ns, node, cookie, cmd,
587		buffer, bufferSize));
588	status_t error = volume->IOCtl(node, cookie, cmd, buffer, bufferSize);
589	PRINT(("userlandfs_ioctl() done: (%lx)\n", error));
590	return error;
591}
592
593// userlandfs_setflags
594static
595int
596userlandfs_setflags(void *ns, void *node, void *cookie, int flags)
597{
598	Volume* volume = (Volume*)ns;
599	PRINT(("userlandfs_setflags(%p, %p, %p, %d)\n", ns, node, cookie, flags));
600	status_t error = volume->SetFlags(node, cookie, flags);
601	PRINT(("userlandfs_setflags() done: (%lx)\n", error));
602	return error;
603}
604
605// userlandfs_select
606static
607int
608userlandfs_select(void *ns, void *node, void *cookie, uint8 event, uint32 ref,
609	selectsync *sync)
610{
611	Volume* volume = (Volume*)ns;
612	PRINT(("userlandfs_select(%p, %p, %p, %hhd, %lu, %p)\n", ns, node, cookie,
613		event, ref, sync));
614	status_t error = volume->Select(node, cookie, event, ref, sync);
615	PRINT(("userlandfs_select() done: (%lx)\n", error));
616	return error;
617}
618
619// userlandfs_deselect
620static
621int
622userlandfs_deselect(void *ns, void *node, void *cookie, uint8 event,
623	selectsync *sync)
624{
625	Volume* volume = (Volume*)ns;
626	PRINT(("userlandfs_deselect(%p, %p, %p, %hhd, %p)\n", ns, node, cookie,
627		event, sync));
628	status_t error = volume->Deselect(node, cookie, event, sync);
629	PRINT(("userlandfs_deselect() done: (%lx)\n", error));
630	return error;
631}
632
633// #pragma mark -
634// #pragma mark ----- hard links / symlinks -----
635
636// userlandfs_link
637static
638int
639userlandfs_link(void *ns, void *dir, const char *name, void *node)
640{
641	Volume* volume = (Volume*)ns;
642	PRINT(("userlandfs_link(%p, %p, `%s', %p)\n", ns, dir, name, node));
643	status_t error = volume->Link(dir, name, node);
644	PRINT(("userlandfs_link() done: (%lx)\n", error));
645	return error;
646}
647
648// userlandfs_unlink
649static
650int
651userlandfs_unlink(void *ns, void *dir, const char *name)
652{
653	Volume* volume = (Volume*)ns;
654	PRINT(("userlandfs_unlink(%p, %p, `%s')\n", ns, dir, name));
655	status_t error = volume->Unlink(dir, name);
656	PRINT(("userlandfs_unlink() done: (%lx)\n", error));
657	return error;
658}
659
660// userlandfs_symlink
661static
662int
663userlandfs_symlink(void *ns, void *dir, const char *name, const char *path)
664{
665	Volume* volume = (Volume*)ns;
666	PRINT(("userlandfs_symlink(%p, %p, `%s', `%s')\n", ns, dir, name, path));
667	status_t error = volume->Symlink(dir, name, path);
668	PRINT(("userlandfs_symlink() done: (%lx)\n", error));
669	return error;
670}
671
672// userlandfs_read_link
673static
674int
675userlandfs_read_link(void *ns, void *node, char *buffer, size_t *bufferSize)
676{
677	Volume* volume = (Volume*)ns;
678	PRINT(("userlandfs_read_link(%p, %p, %p, %lu)\n", ns, node, buffer,
679		*bufferSize));
680	status_t error = volume->ReadLink(node, buffer, *bufferSize, bufferSize);
681	PRINT(("userlandfs_read_link() done: (%lx, %lu)\n", error, *bufferSize));
682	return error;
683}
684
685// userlandfs_rename
686static
687int
688userlandfs_rename(void *ns, void *oldDir, const char *oldName, void *newDir,
689	const char *newName)
690{
691	Volume* volume = (Volume*)ns;
692	PRINT(("userlandfs_rename(%p, %p, `%s', %p, `%s')\n", ns, oldDir, oldName,
693		newDir, newName));
694	status_t error = volume->Rename(oldDir, oldName, newDir, newName);
695	PRINT(("userlandfs_rename() done: (%lx)\n", error));
696	return error;
697}
698
699// #pragma mark -
700// #pragma mark ----- directories -----
701
702// userlandfs_mkdir
703static
704int
705userlandfs_mkdir(void *ns, void *dir, const char *name, int mode)
706{
707	Volume* volume = (Volume*)ns;
708	PRINT(("userlandfs_mkdir(%p, %p, `%s', %d)\n", ns, dir, name, mode));
709	status_t error = volume->MkDir(dir, name, mode);
710	PRINT(("userlandfs_mkdir() done: (%lx)\n", error));
711	return error;
712}
713
714// userlandfs_rmdir
715static
716int
717userlandfs_rmdir(void *ns, void *dir, const char *name)
718{
719	Volume* volume = (Volume*)ns;
720	PRINT(("userlandfs_rmdir(%p, %p, `%s')\n", ns, dir, name));
721	status_t error = volume->RmDir(dir, name);
722	PRINT(("userlandfs_rmdir() done: (%lx)\n", error));
723	return error;
724}
725
726// userlandfs_open_dir
727static
728int
729userlandfs_open_dir(void *ns, void *node, void **cookie)
730{
731	Volume* volume = (Volume*)ns;
732	PRINT(("userlandfs_open_dir(%p, %p)\n", ns, node));
733	status_t error = volume->OpenDir(node, cookie);
734	PRINT(("userlandfs_open_dir() done: (%lx, %p)\n", error, *cookie));
735	return error;
736}
737
738// userlandfs_close_dir
739static
740int
741userlandfs_close_dir(void *ns, void *node, void *cookie)
742{
743	Volume* volume = (Volume*)ns;
744	PRINT(("userlandfs_close_dir(%p, %p, %p)\n", ns, node, cookie));
745	status_t error = volume->CloseDir(node, cookie);
746	PRINT(("userlandfs_close_dir() done: %lx\n", error));
747	return error;
748}
749
750// userlandfs_free_dir_cookie
751static
752int
753userlandfs_free_dir_cookie(void *ns, void *node, void *cookie)
754{
755	Volume* volume = (Volume*)ns;
756	PRINT(("userlandfs_free_dir_cookie(%p, %p, %p)\n", ns, node, cookie));
757	status_t error = volume->FreeDirCookie(node, cookie);
758	PRINT(("userlandfs_free_dir_cookie() done: %lx \n", error));
759	return error;
760}
761
762// userlandfs_read_dir
763static
764int
765userlandfs_read_dir(void *ns, void *node, void *cookie, long *count,
766	struct dirent *buffer, size_t bufferSize)
767{
768	Volume* volume = (Volume*)ns;
769	PRINT(("userlandfs_read_dir(%p, %p, %p, %ld, %p, %lu)\n", ns, node, cookie,
770		*count, buffer, bufferSize));
771	status_t error = volume->ReadDir(node, cookie, buffer, bufferSize, *count,
772		count);
773	PRINT(("userlandfs_read_dir() done: (%lx, %ld)\n", error, *count));
774	#if DEBUG
775		dirent* entry = buffer;
776		for (int32 i = 0; i < *count; i++) {
777			// R5's kernel vsprintf() doesn't seem to know `%.<number>s', so
778			// we need to work around.
779			char name[B_FILE_NAME_LENGTH];
780			int nameLen = strnlen(entry->d_name, B_FILE_NAME_LENGTH - 1);
781			strncpy(name, entry->d_name, nameLen);
782			name[nameLen] = '\0';
783			PRINT(("  entry: d_dev: %ld, d_pdev: %ld, d_ino: %Ld, d_pino: %Ld, "
784				"d_reclen: %hu, d_name: `%s'\n",
785				entry->d_dev, entry->d_pdev, entry->d_ino, entry->d_pino,
786				entry->d_reclen, name));
787			entry = (dirent*)((char*)entry + entry->d_reclen);
788		}
789	#endif
790	return error;
791}
792
793// userlandfs_rewind_dir
794static
795int
796userlandfs_rewind_dir(void *ns, void *node, void *cookie)
797{
798	Volume* volume = (Volume*)ns;
799	PRINT(("userlandfs_rewind_dir(%p, %p, %p)\n", ns, node, cookie));
800	status_t error = volume->RewindDir(node, cookie);
801	PRINT(("userlandfs_rewind_dir() done: %lx\n", error));
802	return error;
803}
804
805// userlandfs_walk
806static
807int
808userlandfs_walk(void *ns, void *dir, const char *entryName,
809	char **resolvedPath, vnode_id *vnid)
810{
811	Volume* volume = (Volume*)ns;
812	PRINT(("userlandfs_walk(%p, %p, `%s', %p, %p)\n", ns, dir,
813		entryName, resolvedPath, vnid));
814	status_t error = volume->Walk(dir, entryName, resolvedPath, vnid);
815	PRINT(("userlandfs_walk() done: (%lx, `%s', %Ld)\n", error,
816		(resolvedPath ? *resolvedPath : NULL), *vnid));
817	return error;
818}
819
820// #pragma mark -
821// #pragma mark ----- attributes -----
822
823// userlandfs_open_attrdir
824static
825int
826userlandfs_open_attrdir(void *ns, void *node, void **cookie)
827{
828	Volume* volume = (Volume*)ns;
829	PRINT(("userlandfs_open_attrdir(%p, %p)\n", ns, node));
830	status_t error = volume->OpenAttrDir(node, cookie);
831	PRINT(("userlandfs_open_attrdir() done: (%lx, %p)\n", error, *cookie));
832	return error;
833}
834
835// userlandfs_close_attrdir
836static
837int
838userlandfs_close_attrdir(void *ns, void *node, void *cookie)
839{
840	Volume* volume = (Volume*)ns;
841	PRINT(("userlandfs_close_attrdir(%p, %p, %p)\n", ns, node, cookie));
842	status_t error = volume->CloseAttrDir(node, cookie);
843	PRINT(("userlandfs_close_attrdir() done: (%lx)\n", error));
844	return error;
845}
846
847// userlandfs_free_attrdir_cookie
848static
849int
850userlandfs_free_attrdir_cookie(void *ns, void *node, void *cookie)
851{
852	Volume* volume = (Volume*)ns;
853	PRINT(("userlandfs_free_attrdir_cookie(%p, %p, %p)\n", ns, node, cookie));
854	status_t error = volume->FreeAttrDirCookie(node, cookie);
855	PRINT(("userlandfs_free_attrdir_cookie() done: (%lx)\n", error));
856	return error;
857}
858
859// userlandfs_read_attrdir
860static
861int
862userlandfs_read_attrdir(void *ns, void *node, void *cookie, long *count,
863	struct dirent *buffer, size_t bufferSize)
864{
865	Volume* volume = (Volume*)ns;
866	PRINT(("userlandfs_read_attrdir(%p, %p, %p, %ld, %p, %lu)\n", ns, node,
867		cookie, *count, buffer, bufferSize));
868	status_t error = volume->ReadAttrDir(node, cookie, buffer, bufferSize,
869		*count, count);
870	PRINT(("userlandfs_read_attrdir() done: (%lx, %ld)\n", error, *count));
871	return error;
872}
873
874// userlandfs_rewind_attrdir
875static
876int
877userlandfs_rewind_attrdir(void *ns, void *node, void *cookie)
878{
879	Volume* volume = (Volume*)ns;
880	PRINT(("userlandfs_rewind_attrdir(%p, %p, %p)\n", ns, node, cookie));
881	status_t error = volume->RewindAttrDir(node, cookie);
882	PRINT(("userlandfs_rewind_attrdir() done: (%lx)\n", error));
883	return error;
884}
885
886// userlandfs_read_attr
887static
888int
889userlandfs_read_attr(void *ns, void *node, const char *name, int type,
890	void *buffer, size_t *bufferSize, off_t pos)
891{
892	Volume* volume = (Volume*)ns;
893	PRINT(("userlandfs_read_attr(%p, %p, `%s', %d, %p, %lu, %Ld)\n", ns, node,
894		name, type, buffer, *bufferSize, pos));
895	status_t error = volume->ReadAttr(node, name, type, pos, buffer,
896		*bufferSize, bufferSize);
897	PRINT(("userlandfs_read_attr() done: (%lx, %ld)\n", error, *bufferSize));
898	return error;
899}
900
901// userlandfs_write_attr
902static
903int
904userlandfs_write_attr(void *ns, void *node, const char *name, int type,
905	const void *buffer, size_t *bufferSize, off_t pos)
906{
907	Volume* volume = (Volume*)ns;
908	PRINT(("userlandfs_write_attr(%p, %p, `%s', %d, %p, %lu, %Ld)\n", ns, node,
909		name, type, buffer, *bufferSize, pos));
910	status_t error = volume->WriteAttr(node, name, type, pos, buffer,
911		*bufferSize, bufferSize);
912	PRINT(("userlandfs_write_attr() done: (%lx, %ld)\n", error, *bufferSize));
913	return error;
914}
915
916// userlandfs_remove_attr
917static
918int
919userlandfs_remove_attr(void *ns, void *node, const char *name)
920{
921	Volume* volume = (Volume*)ns;
922	PRINT(("userlandfs_remove_attr(%p, %p, `%s')\n", ns, node, name));
923	status_t error = volume->RemoveAttr(node, name);
924	PRINT(("userlandfs_remove_attr() done: (%lx)\n", error));
925	return error;
926}
927
928// userlandfs_rename_attr
929static
930int
931userlandfs_rename_attr(void *ns, void *node, const char *oldName,
932	const char *newName)
933{
934	Volume* volume = (Volume*)ns;
935	PRINT(("userlandfs_rename_attr(%p, %p, `%s', `%s')\n", ns, node, oldName,
936		newName));
937	status_t error = volume->RenameAttr(node, oldName, newName);
938	PRINT(("userlandfs_rename_attr() done: (%lx)\n", error));
939	return error;
940}
941
942// userlandfs_stat_attr
943static
944int
945userlandfs_stat_attr(void *ns, void *node, const char *name,
946	struct attr_info *attrInfo)
947{
948	Volume* volume = (Volume*)ns;
949	PRINT(("userlandfs_stat_attr(%p, %p, `%s', %p)\n", ns, node, name,
950		attrInfo));
951	status_t error = volume->StatAttr(node, name, attrInfo);
952	PRINT(("userlandfs_stat_attr() done: (%lx)\n", error));
953	return error;
954}
955
956// #pragma mark -
957// #pragma mark ----- indices -----
958
959// userlandfs_open_indexdir
960static
961int
962userlandfs_open_indexdir(void *ns, void **cookie)
963{
964	Volume* volume = (Volume*)ns;
965	PRINT(("userlandfs_open_indexdir(%p, %p)\n", ns, cookie));
966	status_t error = volume->OpenIndexDir(cookie);
967	PRINT(("userlandfs_open_indexdir() done: (%lx, %p)\n", error, *cookie));
968	return error;
969}
970
971// userlandfs_close_indexdir
972static
973int
974userlandfs_close_indexdir(void *ns, void *cookie)
975{
976	Volume* volume = (Volume*)ns;
977	PRINT(("userlandfs_close_indexdir(%p, %p)\n", ns, cookie));
978	status_t error = volume->CloseIndexDir(cookie);
979	PRINT(("userlandfs_close_indexdir() done: (%lx)\n", error));
980	return error;
981}
982
983// userlandfs_free_indexdir_cookie
984static
985int
986userlandfs_free_indexdir_cookie(void *ns, void *node, void *cookie)
987{
988	Volume* volume = (Volume*)ns;
989	PRINT(("userlandfs_free_indexdir_cookie(%p, %p)\n", ns, cookie));
990	status_t error = volume->FreeIndexDirCookie(cookie);
991	PRINT(("userlandfs_free_indexdir_cookie() done: (%lx)\n", error));
992	return error;
993}
994
995// userlandfs_read_indexdir
996static
997int
998userlandfs_read_indexdir(void *ns, void *cookie, long *count,
999	struct dirent *buffer, size_t bufferSize)
1000{
1001	Volume* volume = (Volume*)ns;
1002	PRINT(("userlandfs_read_indexdir(%p, %p, %ld, %p, %lu)\n", ns, cookie,
1003		*count, buffer, bufferSize));
1004	status_t error = volume->ReadIndexDir(cookie, buffer, bufferSize,
1005		*count, count);
1006	PRINT(("userlandfs_read_indexdir() done: (%lx, %ld)\n", error, *count));
1007	return error;
1008}
1009
1010// userlandfs_rewind_indexdir
1011static
1012int
1013userlandfs_rewind_indexdir(void *ns, void *cookie)
1014{
1015	Volume* volume = (Volume*)ns;
1016	PRINT(("userlandfs_rewind_indexdir(%p, %p)\n", ns, cookie));
1017	status_t error = volume->RewindIndexDir(cookie);
1018	PRINT(("userlandfs_rewind_indexdir() done: (%lx)\n", error));
1019	return error;
1020}
1021
1022// userlandfs_create_index
1023static
1024int
1025userlandfs_create_index(void *ns, const char *name, int type, int flags)
1026{
1027	Volume* volume = (Volume*)ns;
1028	PRINT(("userlandfs_create_index(%p, `%s', %d, %d)\n", ns, name, type,
1029		flags));
1030	status_t error = volume->CreateIndex(name, type, flags);
1031	PRINT(("userlandfs_create_index() done: (%lx)\n", error));
1032	return error;
1033}
1034
1035// userlandfs_remove_index
1036static
1037int
1038userlandfs_remove_index(void *ns, const char *name)
1039{
1040	Volume* volume = (Volume*)ns;
1041	PRINT(("userlandfs_remove_index(%p, `%s')\n", ns, name));
1042	status_t error = volume->RemoveIndex(name);
1043	PRINT(("userlandfs_remove_index() done: (%lx)\n", error));
1044	return error;
1045}
1046
1047// userlandfs_rename_index
1048static
1049int
1050userlandfs_rename_index(void *ns, const char *oldName, const char *newName)
1051{
1052	Volume* volume = (Volume*)ns;
1053	PRINT(("userlandfs_rename_index(%p, `%s', `%s')\n", ns, oldName, newName));
1054	status_t error = volume->RenameIndex(oldName, newName);
1055	PRINT(("userlandfs_rename_index() done: (%lx)\n", error));
1056	return error;
1057}
1058
1059// userlandfs_stat_index
1060static
1061int
1062userlandfs_stat_index(void *ns, const char *name, struct index_info *indexInfo)
1063{
1064	Volume* volume = (Volume*)ns;
1065	PRINT(("userlandfs_stat_index(%p, `%s', %p)\n", ns, name, indexInfo));
1066	status_t error = volume->StatIndex(name, indexInfo);
1067	PRINT(("userlandfs_stat_index() done: (%lx)\n", error));
1068	return error;
1069}
1070
1071// #pragma mark -
1072// #pragma mark ----- queries -----
1073
1074// userlandfs_open_query
1075static
1076int
1077userlandfs_open_query(void *ns, const char *queryString, ulong flags,
1078	port_id port, long token, void **cookie)
1079{
1080	Volume* volume = (Volume*)ns;
1081	PRINT(("userlandfs_open_query(%p, `%s', %lu, %ld, %ld, %p)\n", ns,
1082		queryString, flags, port, token, cookie));
1083	status_t error = volume->OpenQuery(queryString, flags, port, token, cookie);
1084	PRINT(("userlandfs_open_query() done: (%lx, %p)\n", error, *cookie));
1085	return error;
1086}
1087
1088// userlandfs_close_query
1089static
1090int
1091userlandfs_close_query(void *ns, void *cookie)
1092{
1093	Volume* volume = (Volume*)ns;
1094	PRINT(("userlandfs_close_query(%p, %p)\n", ns, cookie));
1095	status_t error = volume->CloseQuery(cookie);
1096	PRINT(("userlandfs_close_query() done: (%lx)\n", error));
1097	return error;
1098}
1099
1100// userlandfs_free_query_cookie
1101static
1102int
1103userlandfs_free_query_cookie(void *ns, void *node, void *cookie)
1104{
1105	Volume* volume = (Volume*)ns;
1106	PRINT(("userlandfs_free_query_cookie(%p, %p)\n", ns, cookie));
1107	status_t error = volume->FreeQueryCookie(cookie);
1108	PRINT(("userlandfs_free_query_cookie() done: (%lx)\n", error));
1109	return error;
1110}
1111
1112// userlandfs_read_query
1113static
1114int
1115userlandfs_read_query(void *ns, void *cookie, long *count,
1116	struct dirent *buffer, size_t bufferSize)
1117{
1118	Volume* volume = (Volume*)ns;
1119	PRINT(("userlandfs_read_query(%p, %p, %ld, %p, %lu)\n", ns, cookie,
1120		*count, buffer, bufferSize));
1121	status_t error = volume->ReadQuery(cookie, buffer, bufferSize,
1122		*count, count);
1123	PRINT(("userlandfs_read_query() done: (%lx, %ld)\n", error, *count));
1124	#if DEBUG
1125		if (*count > 0) {
1126			// R5's kernel vsprintf() doesn't seem to know `%.<number>s', so
1127			// we need to work around.
1128			char name[B_FILE_NAME_LENGTH];
1129			int nameLen = strnlen(buffer->d_name, B_FILE_NAME_LENGTH - 1);
1130			strncpy(name, buffer->d_name, nameLen);
1131			name[nameLen] = '\0';
1132			PRINT(("  entry: d_dev: %ld, d_pdev: %ld, d_ino: %Ld, d_pino: %Ld, "
1133				"d_reclen: %hu, d_name: `%s'\n",
1134				buffer->d_dev, buffer->d_pdev, buffer->d_ino, buffer->d_pino,
1135				buffer->d_reclen, name));
1136		}
1137	#endif
1138	return error;
1139}
1140
1141