1/*
2 * Copyright 2001-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6#include "kernel_interface.h"
7
8#include <dirent.h>
9
10#include <KernelExport.h>
11#include <fs_interface.h>
12
13#include "Debug.h"
14#include "FileSystem.h"
15#include "String.h"
16#include "UserlandFS.h"
17#include "Volume.h"
18
19
20// #pragma mark - general
21
22
23// parse_parameters
24static status_t
25parse_parameters(const char *parameters, String &fsName,
26	const char **fsParameters)
27{
28	// check parameters
29	if (!parameters)
30		return B_BAD_VALUE;
31
32	int32 len = strlen(parameters);
33
34	// skip leading white space
35	for (; len > 0; parameters++, len--) {
36		if (*parameters != ' ' && *parameters != '\t' && *parameters != '\n')
37			break;
38	}
39	if (len == 0)
40		return B_BAD_VALUE;
41
42	// get the file system name
43	int32 fsNameLen = len;
44	for (int32 i = 0; i < len; i++) {
45		if (parameters[i] == ' ' || parameters[i] == '\t'
46			|| parameters[i] == '\n') {
47			fsNameLen = i;
48			break;
49		}
50	}
51
52	fsName.SetTo(parameters, fsNameLen);
53	if (fsName.GetLength() == 0) {
54		exit_debugging();
55		return B_NO_MEMORY;
56	}
57	parameters += fsNameLen;
58	len -= fsNameLen;
59
60	// skip leading white space of the FS parameters
61	for (; len > 0; parameters++, len--) {
62		if (*parameters != ' ' && *parameters != '\t' && *parameters != '\n')
63			break;
64	}
65	*fsParameters = parameters;
66
67	return B_OK;
68}
69
70// userlandfs_mount
71static status_t
72userlandfs_mount(fs_volume* fsVolume, const char* device, uint32 flags,
73	const char* args, ino_t* rootVnodeID)
74{
75	PRINT(("userlandfs_mount(%p (%" B_PRId32 "), %s, 0x%" B_PRIx32
76		", %s, %p)\n", fsVolume, fsVolume->id, device, flags, args,
77		rootVnodeID));
78
79	status_t error = B_OK;
80
81	// get the parameters
82// TODO: The parameters are in driver settings format now.
83	String fsName;
84	const char* fsParameters;
85	error = parse_parameters(args, fsName, &fsParameters);
86	if (error != B_OK)
87		RETURN_ERROR(error);
88
89	// get the UserlandFS object
90	UserlandFS* userlandFS = UserlandFS::GetUserlandFS();
91	if (!userlandFS)
92		RETURN_ERROR(B_ERROR);
93
94	// get the file system
95	FileSystem* fileSystem = NULL;
96	error = userlandFS->RegisterFileSystem(fsName.GetString(), &fileSystem);
97	if (error != B_OK)
98		RETURN_ERROR(error);
99
100	// mount the volume
101	Volume* volume = NULL;
102	error = fileSystem->Mount(fsVolume, device, flags, fsParameters, &volume);
103	if (error != B_OK) {
104		userlandFS->UnregisterFileSystem(fileSystem);
105		RETURN_ERROR(error);
106	}
107
108	fsVolume->private_volume = volume;
109	fsVolume->ops = volume->GetVolumeOps();
110	*rootVnodeID = volume->GetRootID();
111
112	PRINT(("userlandfs_mount() done: %p, %" B_PRIdINO "\n",
113		fsVolume->private_volume, *rootVnodeID));
114
115	return error;
116}
117
118// userlandfs_unmount
119static status_t
120userlandfs_unmount(fs_volume* fsVolume)
121{
122	Volume* volume = (Volume*)fsVolume->private_volume;
123	PRINT(("userlandfs_unmount(%p)\n", volume));
124
125	FileSystem* fileSystem = volume->GetFileSystem();
126	status_t error = volume->Unmount();
127	// The error code the FS's unmount hook returns is completely irrelevant to
128	// the VFS. It considers the volume unmounted in any case.
129	volume->ReleaseReference();
130	UserlandFS::GetUserlandFS()->UnregisterFileSystem(fileSystem);
131
132	PRINT(("userlandfs_unmount() done: %" B_PRIx32 "\n", error));
133	return error;
134}
135
136// userlandfs_sync
137static status_t
138userlandfs_sync(fs_volume* fsVolume)
139{
140	Volume* volume = (Volume*)fsVolume->private_volume;
141	PRINT(("userlandfs_sync(%p)\n", volume));
142	status_t error = volume->Sync();
143	PRINT(("userlandfs_sync() done: %" B_PRIx32 "\n", error));
144	return error;
145}
146
147// userlandfs_read_fs_info
148static status_t
149userlandfs_read_fs_info(fs_volume* fsVolume, struct fs_info* info)
150{
151	Volume* volume = (Volume*)fsVolume->private_volume;
152	PRINT(("userlandfs_read_fs_info(%p, %p)\n", volume, info));
153	status_t error = volume->ReadFSInfo(info);
154	PRINT(("userlandfs_read_fs_info() done: %" B_PRIx32 "\n", error));
155	return error;
156}
157
158// userlandfs_write_fs_info
159static status_t
160userlandfs_write_fs_info(fs_volume* fsVolume, const struct fs_info* info,
161	uint32 mask)
162{
163	Volume* volume = (Volume*)fsVolume->private_volume;
164	PRINT(("userlandfs_write_fs_info(%p, %p, 0x%" B_PRIx32 ")\n", volume, info,
165		mask));
166	status_t error = volume->WriteFSInfo(info, mask);
167	PRINT(("userlandfs_write_fs_info() done: %" B_PRIx32 "\n", error));
168	return error;
169}
170
171
172// #pragma mark - vnodes
173
174
175// userlandfs_lookup
176static status_t
177userlandfs_lookup(fs_volume* fsVolume, fs_vnode* fsDir, const char* entryName,
178	ino_t* vnid)
179{
180	Volume* volume = (Volume*)fsVolume->private_volume;
181	PRINT(("userlandfs_lookup(%p, %p, `%s', %p)\n", volume, fsDir->private_node,
182		entryName, vnid));
183	status_t error = volume->Lookup(fsDir->private_node, entryName, vnid);
184	PRINT(("userlandfs_lookup() done: (%" B_PRIx32 ", %" B_PRIdINO ")\n", error,
185		*vnid));
186	return error;
187}
188
189// userlandfs_get_vnode_name
190static status_t
191userlandfs_get_vnode_name(fs_volume* fsVolume, fs_vnode* fsNode, char* buffer,
192	size_t bufferSize)
193{
194	Volume* volume = (Volume*)fsVolume->private_volume;
195	PRINT(("userlandfs_get_vnode_name(%p, %p, %p, %" B_PRIuSIZE ")\n", volume,
196		fsNode->private_node, buffer, bufferSize));
197	status_t error = volume->GetVNodeName(fsNode->private_node, buffer,
198		bufferSize);
199	PRINT(("userlandfs_get_vnode_name() done: (%" B_PRIx32 ", \"%.*s\")\n",
200		error, (int)bufferSize, (error == B_OK ? buffer : NULL)));
201	return error;
202}
203
204// userlandfs_get_vnode
205static status_t
206userlandfs_get_vnode(fs_volume* fsVolume, ino_t vnid, fs_vnode* fsNode,
207	int* _type, uint32* _flags, bool reenter)
208{
209	Volume* volume = (Volume*)fsVolume->private_volume;
210	PRINT(("userlandfs_get_vnode(%p, %" B_PRIdINO ", %p, %d)\n", volume, vnid,
211		fsNode->private_node, reenter));
212	void* node;
213	fs_vnode_ops* ops;
214	status_t error = volume->ReadVNode(vnid, reenter, &node, &ops, _type,
215		_flags);
216	if (error == B_OK) {
217		fsNode->private_node = node;
218		fsNode->ops = ops;
219	}
220
221	PRINT(("userlandfs_get_vnode() done: (%" B_PRIx32 ", %p, %#x, %#" B_PRIx32
222		")\n", error, node, *_type, *_flags));
223	return error;
224}
225
226// userlandfs_put_vnode
227static status_t
228userlandfs_put_vnode(fs_volume* fsVolume, fs_vnode* fsNode, bool reenter)
229{
230	Volume* volume = (Volume*)fsVolume->private_volume;
231// DANGER: If dbg_printf() is used, this thread will enter another FS and
232// even perform a write operation. The is dangerous here, since this hook
233// may be called out of the other FSs, since, for instance a put_vnode()
234// called from another FS may cause the VFS layer to free vnodes and thus
235// invoke this hook.
236//	PRINT(("userlandfs_put_vnode(%p, %p, %d)\n", volume, fsNode->private_node,
237//		reenter));
238	status_t error = volume->WriteVNode(fsNode->private_node, reenter);
239//	PRINT(("userlandfs_put_vnode() done: %" B_PRIx32 "\n", error));
240	return error;
241}
242
243// userlandfs_remove_vnode
244static status_t
245userlandfs_remove_vnode(fs_volume* fsVolume, fs_vnode* fsNode, bool reenter)
246{
247	Volume* volume = (Volume*)fsVolume->private_volume;
248// DANGER: See userlandfs_write_vnode().
249//	PRINT(("userlandfs_remove_vnode(%p, %p, %d)\n", volume,
250//		fsNode->private_node, reenter));
251	status_t error = volume->RemoveVNode(fsNode->private_node, reenter);
252//	PRINT(("userlandfs_remove_vnode() done: %" B_PRIx32 "\n", error));
253	return error;
254}
255
256
257// #pragma mark - asynchronous I/O
258
259
260// userlandfs_io
261status_t
262userlandfs_io(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie,
263	io_request* request)
264{
265	Volume* volume = (Volume*)fsVolume->private_volume;
266	PRINT(("userlandfs_io(%p, %p, %p, %p)\n", volume, fsNode->private_node,
267		cookie, request));
268	status_t error = volume->DoIO(fsNode->private_node, cookie, request);
269	PRINT(("userlandfs_io() done: (%" B_PRIx32 ")\n", error));
270	return error;
271}
272
273
274// userlandfs_cancel_io
275status_t
276userlandfs_cancel_io(fs_volume* fsVolume, fs_vnode* fsNode, void *cookie,
277	io_request *request)
278{
279	Volume* volume = (Volume*)fsVolume->private_volume;
280	PRINT(("userlandfs_cancel_io(%p, %p, %p, %p)\n", volume,
281		fsNode->private_node, cookie, request));
282	status_t error = volume->CancelIO(fsNode->private_node, cookie, request);
283	PRINT(("userlandfs_cancel_io() done: (%" B_PRIx32 ")\n", error));
284	return error;
285}
286
287
288// #pragma mark - common
289
290
291// userlandfs_ioctl
292static status_t
293userlandfs_ioctl(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie, uint32 op,
294	void* buffer, size_t length)
295{
296	Volume* volume = (Volume*)fsVolume->private_volume;
297	PRINT(("userlandfs_ioctl(%p, %p, %p, %" B_PRIu32 ", %p, %" B_PRIuSIZE ")\n",
298		volume, fsNode->private_node, cookie, op, buffer, length));
299	status_t error = volume->IOCtl(fsNode->private_node, cookie, op, buffer,
300		length);
301	PRINT(("userlandfs_ioctl() done: (%" B_PRIx32 ")\n", error));
302	return error;
303}
304
305// userlandfs_set_flags
306static status_t
307userlandfs_set_flags(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie,
308	int flags)
309{
310	Volume* volume = (Volume*)fsVolume->private_volume;
311	PRINT(("userlandfs_set_flags(%p, %p, %p, %d)\n", volume,
312		fsNode->private_node, cookie, flags));
313	status_t error = volume->SetFlags(fsNode->private_node, cookie, flags);
314	PRINT(("userlandfs_set_flags() done: (%" B_PRIx32 ")\n", error));
315	return error;
316}
317
318// userlandfs_select
319static status_t
320userlandfs_select(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie,
321	uint8 event, selectsync* sync)
322{
323	Volume* volume = (Volume*)fsVolume->private_volume;
324	PRINT(("userlandfs_select(%p, %p, %p, %hhd, %p)\n", volume,
325		fsNode->private_node, cookie, event, sync));
326	status_t error = volume->Select(fsNode->private_node, cookie, event, sync);
327	PRINT(("userlandfs_select() done: (%" B_PRIx32 ")\n", error));
328	return error;
329}
330
331// userlandfs_deselect
332static status_t
333userlandfs_deselect(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie,
334	uint8 event, selectsync* sync)
335{
336	Volume* volume = (Volume*)fsVolume->private_volume;
337	PRINT(("userlandfs_deselect(%p, %p, %p, %hhd, %p)\n", volume,
338		fsNode->private_node, cookie, event, sync));
339	status_t error = volume->Deselect(fsNode->private_node, cookie, event,
340		sync);
341	PRINT(("userlandfs_deselect() done: (%" B_PRIx32 ")\n", error));
342	return error;
343}
344
345// userlandfs_fsync
346static status_t
347userlandfs_fsync(fs_volume* fsVolume, fs_vnode* fsNode)
348{
349	Volume* volume = (Volume*)fsVolume->private_volume;
350	PRINT(("userlandfs_fsync(%p, %p)\n", volume, fsNode->private_node));
351	status_t error = volume->FSync(fsNode->private_node);
352	PRINT(("userlandfs_fsync() done: %" B_PRIx32 "\n", error));
353	return error;
354}
355
356// userlandfs_read_symlink
357static status_t
358userlandfs_read_symlink(fs_volume* fsVolume, fs_vnode* fsLink, char* buffer,
359	size_t* bufferSize)
360{
361	Volume* volume = (Volume*)fsVolume->private_volume;
362	PRINT(("userlandfs_read_symlink(%p, %p, %p, %" B_PRIuSIZE ")\n", volume,
363		fsLink->private_node, buffer, *bufferSize));
364	status_t error = volume->ReadSymlink(fsLink->private_node, buffer,
365		*bufferSize, bufferSize);
366	PRINT(("userlandfs_read_symlink() done: (%" B_PRIx32 ", %" B_PRIuSIZE ")\n",
367		error, *bufferSize));
368	return error;
369}
370
371// userlandfs_create_symlink
372static status_t
373userlandfs_create_symlink(fs_volume* fsVolume, fs_vnode* fsDir,
374	const char* name, const char* path, int mode)
375{
376	Volume* volume = (Volume*)fsVolume->private_volume;
377	PRINT(("userlandfs_create_symlink(%p, %p, `%s', `%s', %d)\n", volume,
378		fsDir->private_node, name, path, mode));
379	status_t error = volume->CreateSymlink(fsDir->private_node, name, path,
380		mode);
381	PRINT(("userlandfs_create_symlink() done: (%" B_PRIx32 ")\n", error));
382	return error;
383}
384
385// userlandfs_link
386static status_t
387userlandfs_link(fs_volume* fsVolume, fs_vnode* fsDir, const char* name,
388	fs_vnode* fsNode)
389{
390	Volume* volume = (Volume*)fsVolume->private_volume;
391	PRINT(("userlandfs_link(%p, %p, `%s', %p)\n", volume,
392		fsDir->private_node, name, fsNode->private_node));
393	status_t error = volume->Link(fsDir->private_node, name,
394		fsNode->private_node);
395	PRINT(("userlandfs_link() done: (%" B_PRIx32 ")\n", error));
396	return error;
397}
398
399// userlandfs_unlink
400static status_t
401userlandfs_unlink(fs_volume* fsVolume, fs_vnode* fsDir, const char* name)
402{
403	Volume* volume = (Volume*)fsVolume->private_volume;
404	PRINT(("userlandfs_unlink(%p, %p, `%s')\n", volume, fsDir->private_node,
405		name));
406	status_t error = volume->Unlink(fsDir->private_node, name);
407	PRINT(("userlandfs_unlink() done: (%" B_PRIx32 ")\n", error));
408	return error;
409}
410
411// userlandfs_rename
412static status_t
413userlandfs_rename(fs_volume* fsVolume, fs_vnode* fsFromDir,
414	const char *fromName, fs_vnode* fsToDir, const char *toName)
415{
416	Volume* volume = (Volume*)fsVolume->private_volume;
417	PRINT(("userlandfs_rename(%p, %p, `%s', %p, `%s')\n", volume,
418		fsFromDir->private_node, fromName, fsToDir->private_node, toName));
419	status_t error = volume->Rename(fsFromDir->private_node, fromName,
420		fsToDir->private_node, toName);
421	PRINT(("userlandfs_rename() done: (%" B_PRIx32 ")\n", error));
422	return error;
423}
424
425// userlandfs_access
426static status_t
427userlandfs_access(fs_volume* fsVolume, fs_vnode* fsNode, int mode)
428{
429	Volume* volume = (Volume*)fsVolume->private_volume;
430	PRINT(("userlandfs_access(%p, %p, %d)\n", volume, fsNode->private_node,
431		mode));
432	status_t error = volume->Access(fsNode->private_node, mode);
433	PRINT(("userlandfs_access() done: %" B_PRIx32 "\n", error));
434	return error;
435}
436
437// userlandfs_read_stat
438static status_t
439userlandfs_read_stat(fs_volume* fsVolume, fs_vnode* fsNode, struct stat* st)
440{
441	Volume* volume = (Volume*)fsVolume->private_volume;
442	PRINT(("userlandfs_read_stat(%p, %p, %p)\n", volume, fsNode->private_node,
443		st));
444	status_t error = volume->ReadStat(fsNode->private_node, st);
445	PRINT(("userlandfs_read_stat() done: %" B_PRIx32 "\n", error));
446	return error;
447}
448
449// userlandfs_write_stat
450static status_t
451userlandfs_write_stat(fs_volume* fsVolume, fs_vnode* fsNode,
452	const struct stat* st, uint32 mask)
453{
454	Volume* volume = (Volume*)fsVolume->private_volume;
455	PRINT(("userlandfs_write_stat(%p, %p, %p, %" B_PRIu32 ")\n", volume,
456		fsNode->private_node, st, mask));
457	status_t error = volume->WriteStat(fsNode->private_node, st, mask);
458	PRINT(("userlandfs_write_stat() done: %" B_PRIx32 "\n", error));
459	return error;
460}
461
462
463// #pragma mark - files
464
465
466// userlandfs_create
467static status_t
468userlandfs_create(fs_volume* fsVolume, fs_vnode* fsDir, const char* name,
469	int openMode, int perms, void** cookie, ino_t* vnid)
470{
471	Volume* volume = (Volume*)fsVolume->private_volume;
472	PRINT(("userlandfs_create(%p, %p, `%s', %d, %d, %p, %p)\n", volume,
473		fsDir->private_node, name, openMode, perms, cookie, vnid));
474	status_t error = volume->Create(fsDir->private_node, name, openMode, perms,
475		cookie, vnid);
476	PRINT(("userlandfs_create() done: (%" B_PRIx32 ", %" B_PRIdINO ", %p)\n",
477		error, *vnid, *cookie));
478	return error;
479}
480
481// userlandfs_open
482static status_t
483userlandfs_open(fs_volume* fsVolume, fs_vnode* fsNode, int openMode,
484	void** cookie)
485{
486	Volume* volume = (Volume*)fsVolume->private_volume;
487	PRINT(("userlandfs_open(%p, %p, %d)\n", volume, fsNode->private_node,
488		openMode));
489	status_t error = volume->Open(fsNode->private_node, openMode, cookie);
490	PRINT(("userlandfs_open() done: (%" B_PRIx32 ", %p)\n", error, *cookie));
491	return error;
492}
493
494// userlandfs_close
495static status_t
496userlandfs_close(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie)
497{
498	Volume* volume = (Volume*)fsVolume->private_volume;
499	PRINT(("userlandfs_close(%p, %p, %p)\n", volume, fsNode->private_node,
500		cookie));
501	status_t error = volume->Close(fsNode->private_node, cookie);
502	PRINT(("userlandfs_close() done: %" B_PRIx32 "\n", error));
503	return error;
504}
505
506// userlandfs_free_cookie
507static status_t
508userlandfs_free_cookie(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie)
509{
510	Volume* volume = (Volume*)fsVolume->private_volume;
511	PRINT(("userlandfs_free_cookie(%p, %p, %p)\n", volume, fsNode->private_node,
512		cookie));
513	status_t error = volume->FreeCookie(fsNode->private_node, cookie);
514	PRINT(("userlandfs_free_cookie() done: %" B_PRIx32 "\n", error));
515	return error;
516}
517
518// userlandfs_read
519static status_t
520userlandfs_read(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie, off_t pos,
521	void* buffer, size_t* length)
522{
523	Volume* volume = (Volume*)fsVolume->private_volume;
524	PRINT(("userlandfs_read(%p, %p, %p, %" B_PRIdOFF ", %p, %" B_PRIuSIZE ")\n",
525		volume, fsNode->private_node, cookie, pos, buffer, *length));
526	status_t error = volume->Read(fsNode->private_node, cookie, pos, buffer,
527		*length, length);
528	PRINT(("userlandfs_read() done: (%" B_PRIx32 ", %" B_PRIuSIZE ")\n", error,
529		*length));
530	return error;
531}
532
533// userlandfs_write
534static status_t
535userlandfs_write(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie, off_t pos,
536	const void* buffer, size_t* length)
537{
538	Volume* volume = (Volume*)fsVolume->private_volume;
539	PRINT(("userlandfs_write(%p, %p, %p, %" B_PRIdOFF ", %p, %" B_PRIuSIZE
540		")\n", volume, fsNode->private_node, cookie, pos, buffer, *length));
541	status_t error = volume->Write(fsNode->private_node, cookie, pos, buffer,
542		*length, length);
543	PRINT(("userlandfs_write() done: (%" B_PRIx32 ", %" B_PRIuSIZE ")\n", error,
544		*length));
545	return error;
546}
547
548
549// #pragma mark - directories
550
551
552// userlandfs_create_dir
553static status_t
554userlandfs_create_dir(fs_volume* fsVolume, fs_vnode* fsParent, const char* name,
555	int perms)
556{
557	Volume* volume = (Volume*)fsVolume->private_volume;
558	PRINT(("userlandfs_create_dir(%p, %p, `%s', %#x)\n", volume,
559		fsParent->private_node, name, perms));
560	status_t error = volume->CreateDir(fsParent->private_node, name, perms);
561	PRINT(("userlandfs_create_dir() done: (%" B_PRIx32 ")\n", error));
562	return error;
563}
564
565// userlandfs_remove_dir
566static status_t
567userlandfs_remove_dir(fs_volume* fsVolume, fs_vnode* fsParent, const char* name)
568{
569	Volume* volume = (Volume*)fsVolume->private_volume;
570	PRINT(("userlandfs_remove_dir(%p, %p, `%s')\n", volume,
571		fsParent->private_node, name));
572	status_t error = volume->RemoveDir(fsParent->private_node, name);
573	PRINT(("userlandfs_remove_dir() done: (%" B_PRIx32 ")\n", error));
574	return error;
575}
576
577// userlandfs_open_dir
578static status_t
579userlandfs_open_dir(fs_volume* fsVolume, fs_vnode* fsNode, void** cookie)
580{
581	Volume* volume = (Volume*)fsVolume->private_volume;
582	PRINT(("userlandfs_open_dir(%p, %p)\n", volume, fsNode->private_node));
583	status_t error = volume->OpenDir(fsNode->private_node, cookie);
584	PRINT(("userlandfs_open_dir() done: (%" B_PRIx32 ", %p)\n", error,
585		*cookie));
586	return error;
587}
588
589// userlandfs_close_dir
590static status_t
591userlandfs_close_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie)
592{
593	Volume* volume = (Volume*)fsVolume->private_volume;
594	PRINT(("userlandfs_close_dir(%p, %p, %p)\n", volume, fsNode->private_node,
595		cookie));
596	status_t error = volume->CloseDir(fsNode->private_node, cookie);
597	PRINT(("userlandfs_close_dir() done: %" B_PRIx32 "\n", error));
598	return error;
599}
600
601// userlandfs_free_dir_cookie
602static status_t
603userlandfs_free_dir_cookie(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie)
604{
605	Volume* volume = (Volume*)fsVolume->private_volume;
606	PRINT(("userlandfs_free_dir_cookie(%p, %p, %p)\n", volume,
607		fsNode->private_node, cookie));
608	status_t error = volume->FreeDirCookie(fsNode->private_node, cookie);
609	PRINT(("userlandfs_free_dir_cookie() done: %" B_PRIx32 "\n", error));
610	return error;
611}
612
613// userlandfs_read_dir
614static status_t
615userlandfs_read_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie,
616	struct dirent* buffer, size_t bufferSize, uint32* count)
617{
618	Volume* volume = (Volume*)fsVolume->private_volume;
619	PRINT(("userlandfs_read_dir(%p, %p, %p, %p, %" B_PRIuSIZE ", %" B_PRIu32
620		")\n", volume, fsNode->private_node, cookie, buffer, bufferSize,
621		*count));
622	status_t error = volume->ReadDir(fsNode->private_node, cookie, buffer,
623		bufferSize, *count, count);
624	PRINT(("userlandfs_read_dir() done: (%" B_PRIx32 ", %" B_PRIu32 ")\n",
625		error, *count));
626	#if DEBUG
627		dirent* entry = buffer;
628		for (uint32 i = 0; error == B_OK && i < *count; i++) {
629			// R5's kernel vsprintf() doesn't seem to know `%.<number>s', so
630			// we need to work around.
631			char name[B_FILE_NAME_LENGTH];
632			int nameLen = strnlen(entry->d_name, B_FILE_NAME_LENGTH - 1);
633			strncpy(name, entry->d_name, nameLen);
634			name[nameLen] = '\0';
635			PRINT(("  entry: d_dev: %" B_PRIdDEV ", d_pdev: %" B_PRIdDEV
636				", d_ino: %" B_PRIdINO ", d_pino: %" B_PRIdINO ", "
637				"d_reclen: %" B_PRIu16 ", d_name: `%s'\n",
638				entry->d_dev, entry->d_pdev, entry->d_ino, entry->d_pino,
639				entry->d_reclen, name));
640			entry = (dirent*)((char*)entry + entry->d_reclen);
641		}
642	#endif
643	return error;
644}
645
646// userlandfs_rewind_dir
647static status_t
648userlandfs_rewind_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie)
649{
650	Volume* volume = (Volume*)fsVolume->private_volume;
651	PRINT(("userlandfs_rewind_dir(%p, %p, %p)\n", volume, fsNode->private_node,
652		cookie));
653	status_t error = volume->RewindDir(fsNode->private_node, cookie);
654	PRINT(("userlandfs_rewind_dir() done: %" B_PRIx32 "\n", error));
655	return error;
656}
657
658
659// #pragma mark - attribute directories
660
661
662// userlandfs_open_attr_dir
663static status_t
664userlandfs_open_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void** cookie)
665{
666	Volume* volume = (Volume*)fsVolume->private_volume;
667	PRINT(("userlandfs_open_attr_dir(%p, %p)\n", volume, fsNode->private_node));
668	status_t error = volume->OpenAttrDir(fsNode->private_node, cookie);
669	PRINT(("userlandfs_open_attr_dir() done: (%" B_PRIx32 ", %p)\n", error,
670		*cookie));
671	return error;
672}
673
674// userlandfs_close_attr_dir
675static status_t
676userlandfs_close_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie)
677{
678	Volume* volume = (Volume*)fsVolume->private_volume;
679	PRINT(("userlandfs_close_attr_dir(%p, %p, %p)\n", volume,
680		fsNode->private_node, cookie));
681	status_t error = volume->CloseAttrDir(fsNode->private_node, cookie);
682	PRINT(("userlandfs_close_attr_dir() done: (%" B_PRIx32 ")\n", error));
683	return error;
684}
685
686// userlandfs_free_attr_dir_cookie
687static status_t
688userlandfs_free_attr_dir_cookie(fs_volume* fsVolume, fs_vnode* fsNode,
689	void* cookie)
690{
691	Volume* volume = (Volume*)fsVolume->private_volume;
692	PRINT(("userlandfs_free_attr_dir_cookie(%p, %p, %p)\n", volume,
693		fsNode->private_node, cookie));
694	status_t error = volume->FreeAttrDirCookie(fsNode->private_node, cookie);
695	PRINT(("userlandfs_free_attr_dir_cookie() done: (%" B_PRIx32 ")\n", error));
696	return error;
697}
698
699// userlandfs_read_attr_dir
700static status_t
701userlandfs_read_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie,
702	struct dirent* buffer, size_t bufferSize, uint32* count)
703{
704	Volume* volume = (Volume*)fsVolume->private_volume;
705	PRINT(("userlandfs_read_attr_dir(%p, %p, %p, %p, %" B_PRIuSIZE ", %"
706		B_PRIu32 ")\n", volume, fsNode->private_node, cookie, buffer,
707		bufferSize, *count));
708	status_t error = volume->ReadAttrDir(fsNode->private_node, cookie, buffer,
709		bufferSize, *count, count);
710	PRINT(("userlandfs_read_attr_dir() done: (%" B_PRIx32 ", %" B_PRIu32 ")\n",
711		error, *count));
712	return error;
713}
714
715// userlandfs_rewind_attr_dir
716static status_t
717userlandfs_rewind_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie)
718{
719	Volume* volume = (Volume*)fsVolume->private_volume;
720	PRINT(("userlandfs_rewind_attr_dir(%p, %p, %p)\n", volume,
721		fsNode->private_node, cookie));
722	status_t error = volume->RewindAttrDir(fsNode->private_node, cookie);
723	PRINT(("userlandfs_rewind_attr_dir() done: (%" B_PRIx32 ")\n", error));
724	return error;
725}
726
727
728// #pragma mark - attributes
729
730
731// userlandfs_create_attr
732status_t
733userlandfs_create_attr(fs_volume* fsVolume, fs_vnode* fsNode, const char* name,
734	uint32 type, int openMode, void** cookie)
735{
736	Volume* volume = (Volume*)fsVolume->private_volume;
737	PRINT(("userlandfs_create_attr(%p, %p, \"%s\", 0x%" B_PRIx32 ", %d, %p)\n",
738		volume, fsNode->private_node, name, type, openMode, cookie));
739	status_t error = volume->CreateAttr(fsNode->private_node, name, type,
740		openMode, cookie);
741	PRINT(("userlandfs_create_attr() done: (%" B_PRIx32 ", %p)\n", error,
742		*cookie));
743	return error;
744}
745
746// userlandfs_open_attr
747status_t
748userlandfs_open_attr(fs_volume* fsVolume, fs_vnode* fsNode, const char* name,
749	int openMode, void** cookie)
750{
751	Volume* volume = (Volume*)fsVolume->private_volume;
752	PRINT(("userlandfs_open_attr(%p, %p, \"%s\", %d, %p)\n", volume,
753		fsNode->private_node, name, openMode, cookie));
754	status_t error = volume->OpenAttr(fsNode->private_node, name, openMode,
755		cookie);
756	PRINT(("userlandfs_open_attr() done: (%" B_PRIx32 ", %p)\n", error,
757		*cookie));
758	return error;
759}
760
761// userlandfs_close_attr
762status_t
763userlandfs_close_attr(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie)
764{
765	Volume* volume = (Volume*)fsVolume->private_volume;
766	PRINT(("userlandfs_close_attr(%p, %p, %p)\n", volume, fsNode->private_node,
767		cookie));
768	status_t error = volume->CloseAttr(fsNode->private_node, cookie);
769	PRINT(("userlandfs_close_attr() done: %" B_PRIx32 "\n", error));
770	return error;
771}
772
773// userlandfs_free_attr_cookie
774status_t
775userlandfs_free_attr_cookie(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie)
776{
777	Volume* volume = (Volume*)fsVolume->private_volume;
778	PRINT(("userlandfs_free_attr_cookie(%p, %p, %p)\n", volume,
779		fsNode->private_node, cookie));
780	status_t error = volume->FreeAttrCookie(fsNode->private_node, cookie);
781	PRINT(("userlandfs_free_attr_cookie() done: %" B_PRIx32 "\n", error));
782	return error;
783}
784
785// userlandfs_read_attr
786static status_t
787userlandfs_read_attr(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie,
788	off_t pos, void* buffer, size_t* length)
789{
790	Volume* volume = (Volume*)fsVolume->private_volume;
791	PRINT(("userlandfs_read_attr(%p, %p, %p, %" B_PRIdOFF ", %p, %"
792		B_PRIuSIZE ")\n", volume, fsNode->private_node, cookie, pos, buffer,
793		*length));
794	status_t error = volume->ReadAttr(fsNode->private_node, cookie, pos, buffer,
795		*length, length);
796	PRINT(("userlandfs_read_attr() done: (%" B_PRIx32 ", %" B_PRIuSIZE ")\n",
797		error, *length));
798	return error;
799}
800
801// userlandfs_write_attr
802static status_t
803userlandfs_write_attr(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie,
804	off_t pos, const void* buffer, size_t* length)
805{
806	Volume* volume = (Volume*)fsVolume->private_volume;
807	PRINT(("userlandfs_write_attr(%p, %p, %p, %" B_PRIdOFF ", %p, %" B_PRIuSIZE
808		")\n", volume, fsNode->private_node, cookie, pos, buffer, *length));
809	status_t error = volume->WriteAttr(fsNode->private_node, cookie, pos,
810		buffer, *length, length);
811	PRINT(("userlandfs_write_attr() done: (%" B_PRIx32 ", %" B_PRIuSIZE ")\n",
812		error, *length));
813	return error;
814}
815
816// userlandfs_read_attr_stat
817static status_t
818userlandfs_read_attr_stat(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie,
819	struct stat* st)
820{
821	Volume* volume = (Volume*)fsVolume->private_volume;
822	PRINT(("userlandfs_read_attr_stat(%p, %p, %p, %p)\n", volume,
823		fsNode->private_node, cookie, st));
824	status_t error = volume->ReadAttrStat(fsNode->private_node, cookie, st);
825	PRINT(("userlandfs_read_attr_stat() done: (%" B_PRIx32 ")\n", error));
826	return error;
827}
828
829// userlandfs_write_attr_stat
830static status_t
831userlandfs_write_attr_stat(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie,
832	const struct stat* st, int statMask)
833{
834	Volume* volume = (Volume*)fsVolume->private_volume;
835	PRINT(("userlandfs_write_attr_stat(%p, %p, %p, %p, 0x%x)\n", volume,
836		fsNode->private_node, cookie, st, statMask));
837	status_t error = volume->WriteAttrStat(fsNode->private_node, cookie, st,
838		statMask);
839	PRINT(("userlandfs_write_attr_stat() done: (%" B_PRIx32 ")\n", error));
840	return error;
841}
842
843// userlandfs_rename_attr
844static status_t
845userlandfs_rename_attr(fs_volume* fsVolume, fs_vnode* fsFromNode,
846	const char* fromName, fs_vnode* fsToNode, const char* toName)
847{
848	Volume* volume = (Volume*)fsVolume->private_volume;
849	PRINT(("userlandfs_rename_attr(%p, %p, `%s', %p, `%s')\n", volume,
850		fsFromNode->private_node, fromName, fsToNode->private_node, toName));
851	status_t error = volume->RenameAttr(fsFromNode->private_node, fromName,
852		fsToNode->private_node, toName);
853	PRINT(("userlandfs_rename_attr() done: (%" B_PRIx32 ")\n", error));
854	return error;
855}
856
857// userlandfs_remove_attr
858static status_t
859userlandfs_remove_attr(fs_volume* fsVolume, fs_vnode* fsNode, const char* name)
860{
861	Volume* volume = (Volume*)fsVolume->private_volume;
862	PRINT(("userlandfs_remove_attr(%p, %p, `%s')\n", volume,
863		fsNode->private_node, name));
864	status_t error = volume->RemoveAttr(fsNode->private_node, name);
865	PRINT(("userlandfs_remove_attr() done: (%" B_PRIx32 ")\n", error));
866	return error;
867}
868
869
870// #pragma mark - indices
871
872
873// userlandfs_open_index_dir
874static status_t
875userlandfs_open_index_dir(fs_volume* fsVolume, void** cookie)
876{
877	Volume* volume = (Volume*)fsVolume->private_volume;
878	PRINT(("userlandfs_open_index_dir(%p, %p)\n", volume, cookie));
879	status_t error = volume->OpenIndexDir(cookie);
880	PRINT(("userlandfs_open_index_dir() done: (%" B_PRIx32 ", %p)\n", error,
881		*cookie));
882	return error;
883}
884
885// userlandfs_close_index_dir
886static status_t
887userlandfs_close_index_dir(fs_volume* fsVolume, void* cookie)
888{
889	Volume* volume = (Volume*)fsVolume->private_volume;
890	PRINT(("userlandfs_close_index_dir(%p, %p)\n", volume, cookie));
891	status_t error = volume->CloseIndexDir(cookie);
892	PRINT(("userlandfs_close_index_dir() done: (%" B_PRIx32 ")\n", error));
893	return error;
894}
895
896// userlandfs_free_index_dir_cookie
897static status_t
898userlandfs_free_index_dir_cookie(fs_volume* fsVolume, void* cookie)
899{
900	Volume* volume = (Volume*)fsVolume->private_volume;
901	PRINT(("userlandfs_free_index_dir_cookie(%p, %p)\n", volume, cookie));
902	status_t error = volume->FreeIndexDirCookie(cookie);
903	PRINT(("userlandfs_free_index_dir_cookie() done: (%" B_PRIx32 ")\n",
904		error));
905	return error;
906}
907
908// userlandfs_read_index_dir
909static status_t
910userlandfs_read_index_dir(fs_volume* fsVolume, void* cookie,
911	struct dirent* buffer, size_t bufferSize, uint32* count)
912{
913	Volume* volume = (Volume*)fsVolume->private_volume;
914	PRINT(("userlandfs_read_index_dir(%p, %p, %p, %" B_PRIuSIZE ", %" B_PRIu32
915		")\n", volume, cookie, buffer, bufferSize, *count));
916	status_t error = volume->ReadIndexDir(cookie, buffer, bufferSize,
917		*count, count);
918	PRINT(("userlandfs_read_index_dir() done: (%" B_PRIx32 ", %" B_PRIu32 ")\n",
919		error, *count));
920	return error;
921}
922
923// userlandfs_rewind_index_dir
924static status_t
925userlandfs_rewind_index_dir(fs_volume* fsVolume, void* cookie)
926{
927	Volume* volume = (Volume*)fsVolume->private_volume;
928	PRINT(("userlandfs_rewind_index_dir(%p, %p)\n", volume, cookie));
929	status_t error = volume->RewindIndexDir(cookie);
930	PRINT(("userlandfs_rewind_index_dir() done: (%" B_PRIx32 ")\n", error));
931	return error;
932}
933
934// userlandfs_create_index
935static status_t
936userlandfs_create_index(fs_volume* fsVolume, const char* name, uint32 type,
937	uint32 flags)
938{
939	Volume* volume = (Volume*)fsVolume->private_volume;
940	PRINT(("userlandfs_create_index(%p, `%s', 0x%" B_PRIx32 ", 0x%" B_PRIx32
941		")\n", volume, name, type, flags));
942	status_t error = volume->CreateIndex(name, type, flags);
943	PRINT(("userlandfs_create_index() done: (%" B_PRIx32 ")\n", error));
944	return error;
945}
946
947// userlandfs_remove_index
948static status_t
949userlandfs_remove_index(fs_volume* fsVolume, const char* name)
950{
951	Volume* volume = (Volume*)fsVolume->private_volume;
952	PRINT(("userlandfs_remove_index(%p, `%s')\n", volume, name));
953	status_t error = volume->RemoveIndex(name);
954	PRINT(("userlandfs_remove_index() done: (%" B_PRIx32 ")\n", error));
955	return error;
956}
957
958// userlandfs_read_index_stat
959static status_t
960userlandfs_read_index_stat(fs_volume* fsVolume, const char* name,
961	struct stat* st)
962{
963	Volume* volume = (Volume*)fsVolume->private_volume;
964	PRINT(("userlandfs_read_index_stat(%p, `%s', %p)\n", volume, name, st));
965	status_t error = volume->ReadIndexStat(name, st);
966	PRINT(("userlandfs_read_index_stat() done: (%" B_PRIx32 ")\n", error));
967	return error;
968}
969
970
971// #pragma mark - queries
972
973
974// userlandfs_open_query
975static status_t
976userlandfs_open_query(fs_volume* fsVolume, const char *queryString,
977	uint32 flags, port_id port, uint32 token, void** cookie)
978{
979	Volume* volume = (Volume*)fsVolume->private_volume;
980	PRINT(("userlandfs_open_query(%p, `%s', %" B_PRIu32 ", %" B_PRId32 ", %"
981		B_PRIu32 ", %p)\n", volume, queryString, flags, port, token, cookie));
982	status_t error = volume->OpenQuery(queryString, flags, port, token, cookie);
983	PRINT(("userlandfs_open_query() done: (%" B_PRIx32 ", %p)\n", error,
984		*cookie));
985	return error;
986}
987
988// userlandfs_close_query
989static status_t
990userlandfs_close_query(fs_volume* fsVolume, void* cookie)
991{
992	Volume* volume = (Volume*)fsVolume->private_volume;
993	PRINT(("userlandfs_close_query(%p, %p)\n", volume, cookie));
994	status_t error = volume->CloseQuery(cookie);
995	PRINT(("userlandfs_close_query() done: (%" B_PRIx32 ")\n", error));
996	return error;
997}
998
999// userlandfs_free_query_cookie
1000static status_t
1001userlandfs_free_query_cookie(fs_volume* fsVolume, void* cookie)
1002{
1003	Volume* volume = (Volume*)fsVolume->private_volume;
1004	PRINT(("userlandfs_free_query_cookie(%p, %p)\n", volume, cookie));
1005	status_t error = volume->FreeQueryCookie(cookie);
1006	PRINT(("userlandfs_free_query_cookie() done: (%" B_PRIx32 ")\n", error));
1007	return error;
1008}
1009
1010// userlandfs_read_query
1011static status_t
1012userlandfs_read_query(fs_volume* fsVolume, void* cookie,
1013	struct dirent* buffer, size_t bufferSize, uint32* count)
1014{
1015	Volume* volume = (Volume*)fsVolume->private_volume;
1016	PRINT(("userlandfs_read_query(%p, %p, %p, %" B_PRIuSIZE ", %" B_PRIu32
1017		")\n", volume, cookie, buffer, bufferSize, *count));
1018	status_t error = volume->ReadQuery(cookie, buffer, bufferSize, *count,
1019		count);
1020	PRINT(("userlandfs_read_query() done: (%" B_PRIx32 ", %" B_PRIu32 ")\n",
1021		error, *count));
1022	#if DEBUG
1023		if (error == B_OK && *count > 0) {
1024			// R5's kernel vsprintf() doesn't seem to know `%.<number>s', so
1025			// we need to work around.
1026			char name[B_FILE_NAME_LENGTH];
1027			int nameLen = strnlen(buffer->d_name, B_FILE_NAME_LENGTH - 1);
1028			strncpy(name, buffer->d_name, nameLen);
1029			name[nameLen] = '\0';
1030			PRINT(("  entry: d_dev: %" B_PRIdDEV ", d_pdev: %" B_PRIdDEV
1031				", d_ino: %" B_PRIdINO ", d_pino: %" B_PRIdINO ", d_reclen: %"
1032				B_PRIu16 ", d_name: `%s'\n", buffer->d_dev, buffer->d_pdev,
1033				buffer->d_ino, buffer->d_pino, buffer->d_reclen, name));
1034		}
1035	#endif
1036	return error;
1037}
1038
1039// userlandfs_rewind_query
1040static status_t
1041userlandfs_rewind_query(fs_volume* fsVolume, void* cookie)
1042{
1043	Volume* volume = (Volume*)fsVolume->private_volume;
1044	PRINT(("userlandfs_rewind_query(%p, %p)\n", volume, cookie));
1045	status_t error = volume->RewindQuery(cookie);
1046	PRINT(("userlandfs_rewind_query() done: (%" B_PRIx32 ")\n", error));
1047	return error;
1048}
1049
1050
1051// userlandfs_initialize
1052/*
1053static status_t
1054userlandfs_initialize(const char *deviceName, void *parameters,
1055	size_t len)
1056{
1057	// get the parameters
1058	String fsName;
1059	const char* fsParameters;
1060	int32 fsParameterLength;
1061	status_t error = parse_parameters(parameters, len, fsName, &fsParameters,
1062		&fsParameterLength);
1063	// make sure there is a UserlandFS we can work with
1064	UserlandFS* userlandFS = NULL;
1065	error = UserlandFS::RegisterUserlandFS(&userlandFS);
1066	if (error != B_OK) {
1067		exit_debugging();
1068		return error;
1069	}
1070	// get the file system
1071	FileSystem* fileSystem = NULL;
1072	if (error == B_OK)
1073		error = userlandFS->RegisterFileSystem(fsName.GetString(), &fileSystem);
1074	// initialize the volume
1075	if (error == B_OK) {
1076		error = fileSystem->Initialize(deviceName, fsParameters,
1077			fsParameterLength);
1078	}
1079	// cleanup
1080	if (fileSystem)
1081		userlandFS->UnregisterFileSystem(fileSystem);
1082	UserlandFS::UnregisterUserlandFS();
1083	return error;
1084}*/
1085
1086
1087
1088// #pragma mark ----- module -----
1089
1090
1091static status_t
1092userlandfs_std_ops(int32 op, ...)
1093{
1094	switch (op) {
1095		case B_MODULE_INIT:
1096		{
1097			init_debugging();
1098			PRINT(("userlandfs_std_ops(): B_MODULE_INIT\n"));
1099
1100			// make sure there is a UserlandFS we can work with
1101			UserlandFS* userlandFS = NULL;
1102			status_t error = UserlandFS::InitUserlandFS(&userlandFS);
1103			if (error != B_OK) {
1104				exit_debugging();
1105				return error;
1106			}
1107
1108			return B_OK;
1109		}
1110
1111		case B_MODULE_UNINIT:
1112			PRINT(("userlandfs_std_ops(): B_MODULE_UNINIT\n"));
1113			UserlandFS::UninitUserlandFS();
1114			exit_debugging();
1115			return B_OK;
1116
1117		default:
1118			return B_ERROR;
1119	}
1120}
1121
1122
1123static file_system_module_info sUserlandFSModuleInfo = {
1124	{
1125		"file_systems/userlandfs" B_CURRENT_FS_API_VERSION,
1126		0,
1127		userlandfs_std_ops,
1128	},
1129
1130	"userlandfs",				// short name
1131	"Userland File System",		// pretty name
1132	0,	// DDM flags
1133
1134	// scanning
1135	NULL,	// identify_partition()
1136	NULL,	// scan_partition()
1137	NULL,	// free_identify_partition_cookie()
1138	NULL,	// free_partition_content_cookie()
1139
1140	// general operations
1141	&userlandfs_mount,
1142
1143	// capability querying
1144	NULL,	// get_supported_operations()
1145	NULL,	// validate_resize()
1146	NULL,	// validate_move()
1147	NULL,	// validate_set_content_name()
1148	NULL,	// validate_set_content_parameters()
1149	NULL,	// validate_initialize()
1150
1151	// shadow partition modification
1152	NULL,	// shadow_changed()
1153
1154	// writing
1155	NULL,	// defragment()
1156	NULL,	// repair()
1157	NULL,	// resize()
1158	NULL,	// move()
1159	NULL,	// set_content_name()
1160	NULL,	// set_content_parameters()
1161	NULL	// initialize()
1162};
1163
1164
1165fs_volume_ops gUserlandFSVolumeOps = {
1166	// general operations
1167	&userlandfs_unmount,
1168	&userlandfs_read_fs_info,
1169	&userlandfs_write_fs_info,
1170	&userlandfs_sync,
1171
1172	&userlandfs_get_vnode,
1173
1174	// index directory & index operations
1175	&userlandfs_open_index_dir,
1176	&userlandfs_close_index_dir,
1177	&userlandfs_free_index_dir_cookie,
1178	&userlandfs_read_index_dir,
1179	&userlandfs_rewind_index_dir,
1180
1181	&userlandfs_create_index,
1182	&userlandfs_remove_index,
1183	&userlandfs_read_index_stat,
1184
1185	// query operations
1186	&userlandfs_open_query,
1187	&userlandfs_close_query,
1188	&userlandfs_free_query_cookie,
1189	&userlandfs_read_query,
1190	&userlandfs_rewind_query,
1191
1192	/* support for FS layers */
1193	NULL,	// all_layers_mounted()
1194	NULL,	// create_sub_vnode()
1195	NULL	// delete_sub_vnode()
1196};
1197
1198
1199fs_vnode_ops gUserlandFSVnodeOps = {
1200	// vnode operations
1201	&userlandfs_lookup,
1202	&userlandfs_get_vnode_name,
1203	&userlandfs_put_vnode,
1204	&userlandfs_remove_vnode,
1205
1206	// VM file access
1207	NULL,	// can_page() -- obsolete
1208	NULL,	// read_pages() -- obsolete
1209	NULL,	// write_pages() -- obsolete
1210
1211	// asynchronous I/O
1212	&userlandfs_io,
1213	&userlandfs_cancel_io,
1214
1215	// cache file access
1216	NULL,	// get_file_map() -- not needed
1217
1218	// common operations
1219	&userlandfs_ioctl,
1220	&userlandfs_set_flags,
1221	&userlandfs_select,
1222	&userlandfs_deselect,
1223	&userlandfs_fsync,
1224
1225	&userlandfs_read_symlink,
1226	&userlandfs_create_symlink,
1227
1228	&userlandfs_link,
1229	&userlandfs_unlink,
1230	&userlandfs_rename,
1231
1232	&userlandfs_access,
1233	&userlandfs_read_stat,
1234	&userlandfs_write_stat,
1235	NULL,	// preallocate()
1236
1237	// file operations
1238	&userlandfs_create,
1239	&userlandfs_open,
1240	&userlandfs_close,
1241	&userlandfs_free_cookie,
1242	&userlandfs_read,
1243	&userlandfs_write,
1244
1245	// directory operations
1246	&userlandfs_create_dir,
1247	&userlandfs_remove_dir,
1248	&userlandfs_open_dir,
1249	&userlandfs_close_dir,
1250	&userlandfs_free_dir_cookie,
1251	&userlandfs_read_dir,
1252	&userlandfs_rewind_dir,
1253
1254	// attribute directory operations
1255	&userlandfs_open_attr_dir,
1256	&userlandfs_close_attr_dir,
1257	&userlandfs_free_attr_dir_cookie,
1258	&userlandfs_read_attr_dir,
1259	&userlandfs_rewind_attr_dir,
1260
1261	// attribute operations
1262	&userlandfs_create_attr,
1263	&userlandfs_open_attr,
1264	&userlandfs_close_attr,
1265	&userlandfs_free_attr_cookie,
1266	&userlandfs_read_attr,
1267	&userlandfs_write_attr,
1268
1269	&userlandfs_read_attr_stat,
1270	&userlandfs_write_attr_stat,
1271	&userlandfs_rename_attr,
1272	&userlandfs_remove_attr,
1273
1274	// support for node and FS layers
1275	NULL,	// create_special_node()
1276	NULL	// get_super_vnode()
1277};
1278
1279
1280module_info *modules[] = {
1281	(module_info *)&sUserlandFSModuleInfo,
1282	NULL,
1283};
1284