xref: /haiku/src/add-ons/kernel/file_systems/nfs/nfs_add_on.c (revision f23596149e0d173463f70629581aa10cc305d32e)
1 #include <posix/stdlib.h>
2 
3 #include "nfs_add_on.h"
4 #include "ksocket.h"
5 
6 #include "rpc.h"
7 #include "pmap.h"
8 #include "nfs.h"
9 #include "mount.h"
10 #include <errno.h>
11 #include <string.h>
12 #include <KernelExport.h>
13 #include <driver_settings.h>
14 #include <sys/stat.h>
15 #include <dirent.h>
16 #include <SupportDefs.h>
17 #include <netinet/udp.h>
18 
19 #define B_UDP_MAX_SIZE UDP_SIZE_MAX
20 
21 /* declare gSocket and others */
22 KSOCKET_MODULE_DECL;
23 
24 /* *** configuration *** */
25 
26 //#define NFS_FS_FLAGS B_FS_IS_SHARED
27 #define NFS_FS_FLAGS B_FS_IS_SHARED|B_FS_IS_PERSISTENT
28 
29 /* port numbers: most NFS servers insist on the client port to be < 1024 (secure option) */
30 /* ports to bind() to; we start at conf_high_port, then go down */
31 static int16 conf_high_port = 1023;
32 static int16 conf_low_port = 900;
33 
34 /* Allow open() to open directories too */
35 static bool conf_allow_dir_open = true;
36 
37 /* Do we list ".." in readdir(rootid) ? (the VFS corrects the dirents anyway) */
38 /* this seems to be mandatory for Dano... BEntry::GetPath() needs that */
39 static bool conf_ls_root_parent = true;
40 
41 /* timeout when waiting for an answer to a call */
42 static bigtime_t conf_call_timeout = 2000000;
43 
44 /* number of retries when waiting for an anwser to a call */
45 static unsigned long conf_call_tries = 3;
46 
47 /* don't check who the answers come from for requests */
48 bool conf_no_check_ip_xid = false;
49 
50 /* *** DEBUG stuff *** */
51 //#define my_notify_listener(p_a, p_b, p_c, p_d, p_e, p_f) ({dprintf("nfs: notify_listener(%08lx)\n", p_a); notify_listener(p_a, p_b, p_c, p_d, p_e, p_f); })
52 #define my_notify_listener notify_listener
53 
54 _EXPORT vnode_ops fs_entry =
55 {
56 	(op_read_vnode *)&fs_read_vnode,
57 	(op_write_vnode *)&fs_write_vnode,
58 	(op_remove_vnode *)&fs_remove_vnode,
59 	(op_secure_vnode *)&fs_secure_vnode,
60 	(op_walk *)&fs_walk,
61 	(op_access *)&fs_access,
62 	(op_create *)&fs_create,
63 	(op_mkdir *)&fs_mkdir,
64 	(op_symlink *)&fs_symlink,
65 	NULL, //	&fs_link,
66 	(op_rename *)&fs_rename,
67 	(op_unlink *)&fs_unlink,
68 	(op_rmdir *)&fs_rmdir,
69 	(op_readlink *)&fs_readlink,
70 	(op_opendir *)&fs_opendir,
71 	(op_closedir *)&fs_closedir,
72 	(op_free_cookie *)&fs_free_dircookie,
73 	(op_rewinddir *)&fs_rewinddir,
74 	(op_readdir *)&fs_readdir,
75 	(op_open *)&fs_open,
76 	(op_close *)&fs_close,
77 	(op_free_cookie *)&fs_free_cookie,
78 	(op_read *)&fs_read,
79 	(op_write *)&fs_write,
80 	NULL, //	&fs_readv,
81 	NULL, //	&fs_writev,
82 	NULL, //	&fs_ioctl,
83 	NULL, //	&fs_setflags,
84 	(op_rstat *)&fs_rstat,
85 	(op_wstat *)&fs_wstat,
86 	NULL, //	&fs_fsync,
87 	NULL, //	&fs_initialize,
88 	(op_mount *)&fs_mount,
89 	(op_unmount *)&fs_unmount,
90 	NULL, //	&fs_sync,
91 	(op_rfsstat *)&fs_rfsstat,
92 	(op_wfsstat *)&fs_wfsstat,
93 	NULL, //	&fs_select,
94 	NULL, //	&fs_deselect,
95 	NULL, //	&fs_open_indexdir,
96 	NULL, //	&fs_close_indexdir,
97 	NULL, //	&fs_free_indexdircookie,
98 	NULL, //	&fs_rewind_indexdir,
99 	NULL, //	&fs_read_indexdir,
100 	NULL, //	&fs_create_index,
101 	NULL, //	&fs_remove_index,
102 	NULL, //	&fs_rename_index,
103 	NULL, //	&fs_stat_index,
104 	NULL, //	&fs_open_attrdir,
105 	NULL, //	&fs_close_attrdir,
106 	NULL, //	&fs_free_attrdircookie,
107 	NULL, //	&fs_rewind_attrdir,
108 	NULL, //	&fs_read_attrdir,
109 	NULL, //	&fs_write_attr,
110 	NULL, //	&fs_read_attr,
111 	NULL, //	&fs_remove_attr,
112 	NULL, //	&fs_rename_attr,
113 	NULL, //	&fs_stat_attr,
114 	NULL, //	&fs_open_query,
115 	NULL, //	&fs_close_query,
116 	NULL, //	&fs_free_querycookie,
117 	NULL, //	&fs_read_query
118 };
119 
120 _EXPORT int32 api_version=B_CUR_FS_API_VERSION;
121 
122 static vint32 refcount = 0; /* we only want to read the config once ? */
123 
124 static status_t read_config(void)
125 {
126 	void *handle;
127 	const char *str, *endptr;
128 	int32 value = 0;
129 
130 	handle = load_driver_settings("nfs");
131 	if (handle == NULL)
132 		return ENOENT;
133 
134 	str = get_driver_parameter(handle, "high_port", NULL, NULL);
135 	if (str) {
136 		endptr = str + strlen(str);
137 		conf_high_port = (int16)strtoul(str, &endptr, 10);
138 	}
139 	str = get_driver_parameter(handle, "low_port", NULL, NULL);
140 	if (str) {
141 		endptr = str + strlen(str);
142 		conf_low_port = (int16)strtoul(str, &endptr, 10);
143 	}
144 
145 	conf_allow_dir_open = get_driver_boolean_parameter(handle, "allow_dir_open", conf_allow_dir_open, true);
146 	conf_ls_root_parent = get_driver_boolean_parameter(handle, "ls_root_parent", conf_ls_root_parent, false);
147 	conf_no_check_ip_xid = get_driver_boolean_parameter(handle, "no_check_ip_xid", conf_no_check_ip_xid, false);
148 
149 	str = get_driver_parameter(handle, "call_timeout", NULL, NULL);
150 	if (str) {
151 		endptr = str + strlen(str);
152 		conf_call_timeout = (bigtime_t)1000 * strtoul(str, &endptr, 10);
153 		if (conf_call_timeout < 1000)
154 			conf_call_timeout = 1000;
155 	}
156 
157 	str = get_driver_parameter(handle, "call_tries", NULL, NULL);
158 	if (str) {
159 		endptr = str + strlen(str);
160 		conf_call_tries = strtoul(str, &endptr, 10);
161 	}
162 
163 	unload_driver_settings(handle);
164 	return B_OK;
165 }
166 
167 extern status_t
168 create_socket(fs_nspace *ns)
169 {
170 	struct sockaddr_in addr;
171 	uint16 port=conf_high_port;
172 
173 	ns->s=ksocket(AF_INET,SOCK_DGRAM,0);
174 
175 	if (ns->s<0)
176 		return errno;
177 
178 	do
179 	{
180 		addr.sin_family=AF_INET;
181 		addr.sin_addr.s_addr=htonl(INADDR_ANY);
182 		//addr.sin_addr.s_addr=htonl(INADDR_LOOPBACK);
183 		addr.sin_port=htons(port);
184 		memset (addr.sin_zero,0,sizeof(addr.sin_zero));
185 
186 		if (kbind(ns->s,(const struct sockaddr *)&addr,sizeof(addr))<0)
187 		{
188 			if (errno!=EADDRINUSE)
189 			{
190 				int result=errno;
191 				kclosesocket(ns->s);
192 				return result;
193 			}
194 
195 			port--;
196 			if (port==conf_low_port)
197 			{
198 				kclosesocket(ns->s);
199 				return B_ERROR;
200 			}
201 		}
202 		else
203 			break;//return B_OK;
204 	}
205 	while (true);
206 
207 	// doesn't seem to help with autoincrementing port on source address...
208 	addr.sin_addr = ns->mountAddr.sin_addr;
209 	addr.sin_port = htons(111);
210 	//kconnect(ns->s,(const struct sockaddr *)&addr,sizeof(addr));
211 
212 	return B_OK;
213 }
214 
215 extern status_t
216 connect_socket(fs_nspace *ns)
217 {
218 	uint16 port=conf_high_port;
219 
220 	struct sockaddr_in addr;
221 	addr.sin_family=AF_INET;
222 	addr.sin_addr.s_addr=htonl(INADDR_ANY);
223 	//addr.sin_addr.s_addr=htonl(INADDR_LOOPBACK);
224 	addr.sin_port=htons(port);
225 	memset (addr.sin_zero,0,sizeof(addr.sin_zero));
226 
227 	if (kconnect(ns->s,(const struct sockaddr *)&ns->nfsAddr,sizeof(ns->nfsAddr))<0)
228 	{
229 		return -1;
230 	}
231 	return B_OK;
232 }
233 
234 extern status_t
235 init_postoffice(fs_nspace *ns)
236 {
237 	status_t result;
238 
239 	ns->tid=spawn_kernel_thread ((thread_func)postoffice_func,"Postoffice",B_NORMAL_PRIORITY,ns);
240 
241 	if (ns->tid<B_OK)
242 		return ns->tid;
243 
244 	ns->quit=false;
245 
246 	result=resume_thread (ns->tid);
247 
248 	if (result<B_OK)
249 	{
250 		kill_thread (ns->tid);
251 
252 		return result;
253 	}
254 
255 	return B_OK;
256 }
257 
258 extern void
259 shutdown_postoffice(fs_nspace *ns)
260 {
261 	struct sockaddr addr;
262 	int addrSize;
263 	status_t result;
264 
265 	ns->quit=true;
266 	kclosesocket(ns->s);
267 
268 	wait_for_thread (ns->tid,&result);
269 }
270 
271 extern status_t
272 postoffice_func(fs_nspace *ns)
273 {
274 	uint8 *buffer=(uint8 *)malloc(B_UDP_MAX_SIZE);
275 
276 	while (!ns->quit)
277 	{
278 		struct sockaddr_in from;
279 		int fromLen=sizeof(from);
280 
281 		ssize_t bytes=krecvfrom (ns->s,buffer,B_UDP_MAX_SIZE,0,(struct sockaddr *)&from,&fromLen);
282 
283 		if (bytes>=4)
284 		{
285 			struct PendingCall *call;
286 			int32 xid=B_BENDIAN_TO_HOST_INT32(*((int32 *)buffer));
287 
288 			call=RPCPendingCallsFindAndRemovePendingCall(&ns->pendingCalls,xid,&from);
289 
290 			if (call)
291 			{
292 				call->buffer=(uint8 *)malloc(bytes);
293 				memcpy (call->buffer,buffer,bytes);
294 
295 				while (release_sem (call->sem)==B_INTERRUPTED);
296 			} else {
297 				dprintf("nfs: postoffice: can't find pending call to remove for xid %d\n", xid);
298 			}
299 		}
300 	}
301 
302 	free (buffer);
303 
304 	return B_OK;
305 }
306 
307 uint8 *send_rpc_call (fs_nspace *ns, const struct sockaddr_in *addr,
308 							int32 prog, int32 vers, int32 proc,
309 							const struct XDROutPacket *packet)
310 {
311 	int32 xid;
312 	size_t authSize;
313 	struct PendingCall *pending;
314 	int32 retries=conf_call_tries;
315 	status_t result;
316 	struct PendingCall *call;
317 
318 	struct XDROutPacket rpc_call;
319 	XDROutPacketInit (&rpc_call);
320 
321 	xid=atomic_add(&ns->xid,1);
322 #ifdef DEBUG_XID
323 	//dbgprintxid(logfd1, xid);
324 #endif
325 
326 	XDROutPacketAddInt32(&rpc_call,xid);
327 	XDROutPacketAddInt32(&rpc_call,RPC_CALL);
328 	XDROutPacketAddInt32(&rpc_call,RPC_VERSION);
329 	XDROutPacketAddInt32(&rpc_call,prog);
330 	XDROutPacketAddInt32(&rpc_call,vers);
331 	XDROutPacketAddInt32(&rpc_call,proc);
332 
333 #if !defined(USE_SYSTEM_AUTHENTICATION)
334 	XDROutPacketAddInt32(&rpc_call,RPC_AUTH_NONE);
335 	XDROutPacketAddDynamic (&rpc_call,NULL,0);
336 #else
337 	XDROutPacketAddInt32(&rpc_call,RPC_AUTH_SYS);
338 	authSize=4+4+((strlen(ns->params.server)+3)&~3)+4+4+4;
339 	XDROutPacketAddInt32(&rpc_call,authSize);
340 	XDROutPacketAddInt32(&rpc_call,0);
341 	XDROutPacketAddString(&rpc_call,ns->params.server);
342 	XDROutPacketAddInt32(&rpc_call,ns->params.uid);
343 	XDROutPacketAddInt32(&rpc_call,ns->params.gid);
344 	XDROutPacketAddInt32(&rpc_call,0);
345 #endif
346 
347 	XDROutPacketAddInt32(&rpc_call,RPC_AUTH_NONE);
348 	XDROutPacketAddDynamic (&rpc_call,NULL,0);
349 
350 	XDROutPacketAppend (&rpc_call,packet);
351 
352 	pending=RPCPendingCallsAddPendingCall(&ns->pendingCalls,xid,addr);
353 #ifdef DEBUG_XID
354 	checksemstate(xid, pending->sem, 0);
355 #endif
356 
357 	do
358 	{
359 		ssize_t bytes;
360 		do
361 		{
362 			bytes=ksendto (ns->s,(const void *)XDROutPacketBuffer(&rpc_call),
363 								XDROutPacketLength(&rpc_call),0,
364 							(const struct sockaddr *)addr,sizeof(*addr));
365 		}
366 		while ((bytes<0)&&(errno==EINTR));
367 
368 		do
369 		{
370 			result=acquire_sem_etc (pending->sem,1,B_TIMEOUT,(retries)?(conf_call_timeout):(2*conf_call_timeout));
371 		}
372 		while (result==B_INTERRUPTED);
373 
374 		retries--;
375 	}
376 	while ((result==B_TIMED_OUT)&&(retries>=0));
377 
378 	if (result>=B_OK)
379 	{
380 		uint8 *buffer=pending->buffer;
381 		pending->buffer=NULL;
382 		SemaphorePoolPut(&ns->pendingCalls.fPool,pending->sem);
383 
384 		PendingCallDestroy(pending);
385 		free(pending);
386 
387 		XDROutPacketDestroy (&rpc_call);
388 		return buffer;
389 	}
390 
391 	// we timed out
392 
393 	call=RPCPendingCallsFindAndRemovePendingCall(&ns->pendingCalls,xid,addr);
394 
395 	kmessage ("nfs: xid %d timed out, removing from queue",xid);
396 
397 #if 0
398 	if (call==NULL)
399 	{
400 #if 1
401 		//XXX:mmu_man:???
402 		while (acquire_sem(pending->sem)==B_INTERRUPTED);
403 #else
404 		status_t err;
405 		/* NOTE(mmu_man): there can be a race condition here where the sem is returned
406 		 * to the pool without the correct value, compromising the next call using it.
407 		 * however it seems waiting forever can lead to lockups...
408 		 */
409 		while ((err = acquire_sem_etc(pending->sem,1,B_TIMEOUT,5000000))==B_INTERRUPTED);
410 		dprintf("nfs: acquire(pending->sem) = 0x%08lx\n", err);
411 		if (err == B_TIMED_OUT)
412 			dprintf("nfs: timed out waiting on sem\n");
413 #endif
414 	}
415 #endif
416 
417 	free(pending->buffer);
418 
419 	/* mmu_man */
420 	if (call) /* if the call has been found and removed (atomic op), the sem hasn't been released */
421 		SemaphorePoolPut(&ns->pendingCalls.fPool,pending->sem);
422 	else
423 		delete_sem(pending->sem); /* else it's in an unknown state, forget it */
424 
425 	PendingCallDestroy (pending);
426 	free(pending);
427 
428 	XDROutPacketDestroy (&rpc_call);
429 	return NULL;
430 }
431 
432 bool is_successful_reply (struct XDRInPacket *reply)
433 {
434 	bool success=false;
435 
436 	int32 xid=XDRInPacketGetInt32(reply);
437 	rpc_msg_type mtype=(rpc_msg_type)XDRInPacketGetInt32(reply);
438 	rpc_reply_stat replyStat=(rpc_reply_stat)XDRInPacketGetInt32(reply);
439 
440 	if (replyStat==RPC_MSG_DENIED)
441 	{
442 		rpc_reject_stat rejectStat=(rpc_reject_stat)XDRInPacketGetInt32(reply);
443 
444 		if (rejectStat==RPC_RPC_MISMATCH)
445 		{
446 			int32 low=XDRInPacketGetInt32(reply);
447 			int32 high=XDRInPacketGetInt32(reply);
448 
449 			kmessage ("RPC_MISMATCH (%d,%d)",low,high);
450 		}
451 		else
452 		{
453 			rpc_auth_stat authStat=(rpc_auth_stat)XDRInPacketGetInt32(reply);
454 
455 			kmessage ("RPC_AUTH_ERROR (%d)",authStat);
456 		}
457 	}
458 	else
459 	{
460 		rpc_auth_flavor flavor=(rpc_auth_flavor)XDRInPacketGetInt32(reply);
461 		char body[400];
462 		size_t bodyLength=XDRInPacketGetDynamic(reply,body);
463 
464 		rpc_accept_stat acceptStat=(rpc_accept_stat)XDRInPacketGetInt32(reply);
465 
466 		if (acceptStat==RPC_PROG_MISMATCH)
467 		{
468 			int32 low=XDRInPacketGetInt32(reply);
469 			int32 high=XDRInPacketGetInt32(reply);
470 
471 			kmessage ("RPC_PROG_MISMATCH (%d,%d)",low,high);
472 		}
473 		else if (acceptStat!=RPC_SUCCESS)
474 			kmessage ("Accepted but failed (%d)",acceptStat);
475 		else
476 			success=true;
477 	}
478 
479 	return success;
480 }
481 
482 status_t get_remote_address (fs_nspace *ns, int32 prog, int32 vers, int32 prot, struct sockaddr_in *addr)
483 {
484 	struct XDROutPacket call;
485 	uint8 *replyBuf;
486 
487 	XDROutPacketInit (&call);
488 
489 	addr->sin_port=htons(PMAP_PORT);
490 
491 	XDROutPacketAddInt32 (&call,prog);
492 	XDROutPacketAddInt32 (&call,vers);
493 	XDROutPacketAddInt32 (&call,prot);
494 	XDROutPacketAddInt32 (&call,0);
495 
496 	replyBuf=send_rpc_call (ns,addr,PMAP_PROGRAM,PMAP_VERSION,PMAPPROC_GETPORT,&call);
497 
498 	if (replyBuf)
499 	{
500 		struct XDRInPacket reply;
501 		XDRInPacketInit (&reply);
502 
503 		XDRInPacketSetTo (&reply,replyBuf,0);
504 
505 		if (is_successful_reply(&reply))
506 		{
507 			addr->sin_port=htons(XDRInPacketGetInt32(&reply));
508 			memset (addr->sin_zero,0,sizeof(addr->sin_zero));
509 
510 			XDRInPacketDestroy(&reply);
511 			XDROutPacketDestroy (&call);
512 			return B_OK;
513 		}
514 
515 		XDRInPacketDestroy(&reply);
516 	}
517 
518 	XDROutPacketDestroy (&call);
519 	return EHOSTUNREACH;
520 }
521 
522 status_t nfs_mount (fs_nspace *ns, const char *path, nfs_fhandle *fhandle)
523 {
524 	struct XDROutPacket call;
525 	struct XDRInPacket reply;
526 	uint8 *replyBuf;
527 	int32 fhstatus;
528 
529 	XDROutPacketInit (&call);
530 	XDRInPacketInit (&reply);
531 
532 	XDROutPacketAddString (&call,path);
533 
534 	replyBuf=send_rpc_call (ns,&ns->mountAddr,MOUNT_PROGRAM,MOUNT_VERSION,MOUNTPROC_MNT,&call);
535 
536 	if (!replyBuf)
537 	{
538 		XDRInPacketDestroy (&reply);
539 		XDROutPacketDestroy (&call);
540 		return EHOSTUNREACH;
541 	}
542 
543 	XDRInPacketSetTo (&reply,replyBuf,0);
544 
545 	if (!is_successful_reply(&reply))
546 	{
547 		XDRInPacketDestroy (&reply);
548 		XDROutPacketDestroy (&call);
549 		return B_ERROR;
550 	}
551 
552 	fhstatus=XDRInPacketGetInt32(&reply);
553 
554 	if (fhstatus!=0)
555 	{
556 		XDRInPacketDestroy (&reply);
557 		XDROutPacketDestroy (&call);
558 		return map_nfs_to_system_error(fhstatus);
559 	}
560 
561 	XDRInPacketGetFixed (&reply,fhandle->opaque,NFS_FHSIZE);
562 
563 	XDRInPacketDestroy (&reply);
564 	XDROutPacketDestroy (&call);
565 	return B_OK;
566 }
567 
568 status_t nfs_lookup (fs_nspace *ns, const nfs_fhandle *dir, const char *filename, nfs_fhandle *fhandle,
569 						struct stat *st)
570 {
571 	struct XDROutPacket call;
572 	struct XDRInPacket reply;
573 	int32 status;
574 	uint8 *replyBuf;
575 
576 	XDROutPacketInit (&call);
577 	XDRInPacketInit (&reply);
578 
579 	XDROutPacketAddFixed (&call,dir->opaque,NFS_FHSIZE);
580 	XDROutPacketAddString (&call,filename);
581 
582 	replyBuf=send_rpc_call (ns,&ns->nfsAddr,NFS_PROGRAM,NFS_VERSION,NFSPROC_LOOKUP,&call);
583 
584 	if (!replyBuf)
585 	{
586 		XDRInPacketDestroy (&reply);
587 		XDROutPacketDestroy (&call);
588 		return EHOSTUNREACH;
589 	}
590 
591 	XDRInPacketSetTo(&reply,replyBuf,0);
592 
593 	if (!is_successful_reply(&reply))
594 	{
595 		XDRInPacketDestroy (&reply);
596 		XDROutPacketDestroy (&call);
597 		return B_ERROR;
598 	}
599 
600 	status=XDRInPacketGetInt32(&reply);
601 
602 	if (status!=NFS_OK)
603 	{
604 		XDRInPacketDestroy (&reply);
605 		XDROutPacketDestroy (&call);
606 		return map_nfs_to_system_error(status);
607 	}
608 
609 	XDRInPacketGetFixed (&reply,fhandle->opaque,NFS_FHSIZE);
610 
611 	if (st)
612 		get_nfs_attr (&reply,st);
613 
614 	XDRInPacketDestroy (&reply);
615 	XDROutPacketDestroy (&call);
616 	return B_OK;
617 }
618 
619 status_t nfs_getattr (fs_nspace *ns, const nfs_fhandle *fhandle,
620 						struct stat *st)
621 {
622 	struct XDROutPacket call;
623 	struct XDRInPacket reply;
624 	uint8 *replyBuf;
625 	int32 status;
626 
627 	XDROutPacketInit (&call);
628 	XDRInPacketInit (&reply);
629 
630 	XDROutPacketAddFixed (&call,fhandle->opaque,NFS_FHSIZE);
631 
632 	replyBuf=send_rpc_call (ns,&ns->nfsAddr,NFS_PROGRAM,NFS_VERSION,NFSPROC_GETATTR,&call);
633 
634 	if (!replyBuf)
635 	{
636 		XDRInPacketDestroy (&reply);
637 		XDROutPacketDestroy (&call);
638 		return EHOSTUNREACH;
639 	}
640 
641 	XDRInPacketSetTo (&reply,replyBuf,0);
642 
643 	if (!is_successful_reply(&reply))
644 	{
645 		XDRInPacketDestroy (&reply);
646 		XDROutPacketDestroy (&call);
647 		return B_ERROR;
648 	}
649 
650 	status=XDRInPacketGetInt32(&reply);
651 
652 	if (status!=NFS_OK)
653 	{
654 		XDRInPacketDestroy (&reply);
655 		XDROutPacketDestroy (&call);
656 		return map_nfs_to_system_error(status);
657 	}
658 
659 	get_nfs_attr (&reply,st);
660 
661 	XDRInPacketDestroy (&reply);
662 	XDROutPacketDestroy (&call);
663 	return B_OK;
664 }
665 
666 extern status_t
667 nfs_truncate_file(fs_nspace *ns, const nfs_fhandle *fhandle, struct stat *st)
668 {
669 	struct XDROutPacket call;
670 	struct XDRInPacket reply;
671 	uint8 *replyBuf;
672 	int32 status;
673 
674 	XDROutPacketInit (&call);
675 	XDRInPacketInit (&reply);
676 
677 	XDROutPacketAddFixed(&call,fhandle->opaque,NFS_FHSIZE);
678 
679 	XDROutPacketAddInt32 (&call,-1);
680 	XDROutPacketAddInt32 (&call,-1);
681 	XDROutPacketAddInt32 (&call,-1);
682 	XDROutPacketAddInt32 (&call,0);
683 	XDROutPacketAddInt32 (&call,time(NULL));
684 	XDROutPacketAddInt32 (&call,0);
685 	XDROutPacketAddInt32 (&call,time(NULL));
686 	XDROutPacketAddInt32 (&call,0);
687 
688 	replyBuf=send_rpc_call (ns,&ns->nfsAddr,NFS_PROGRAM,NFS_VERSION,NFSPROC_SETATTR,&call);
689 
690 	if (!replyBuf)
691 	{
692 		XDRInPacketDestroy (&reply);
693 		XDROutPacketDestroy (&call);
694 		return EHOSTUNREACH;
695 	}
696 
697 	XDRInPacketSetTo(&reply,replyBuf,0);
698 
699 	if (!is_successful_reply(&reply))
700 	{
701 		XDRInPacketDestroy (&reply);
702 		XDROutPacketDestroy (&call);
703 		return B_ERROR;
704 	}
705 
706 	status=XDRInPacketGetInt32(&reply);
707 
708 	if (status!=NFS_OK)
709 	{
710 		XDRInPacketDestroy (&reply);
711 		XDROutPacketDestroy (&call);
712 		return map_nfs_to_system_error(status);
713 	}
714 
715 	if (st)
716 		get_nfs_attr (&reply,st);
717 
718 	XDRInPacketDestroy (&reply);
719 	XDROutPacketDestroy (&call);
720 	return B_OK;
721 }
722 
723 void get_nfs_attr (struct XDRInPacket *reply, struct stat *st)
724 {
725 	nfs_ftype ftype=(nfs_ftype)XDRInPacketGetInt32(reply);
726 	st->st_mode=XDRInPacketGetInt32(reply);
727 
728 	st->st_dev=0;	// just to be sure
729 	st->st_nlink=XDRInPacketGetInt32(reply);
730 	st->st_uid=XDRInPacketGetInt32(reply);
731 	st->st_gid=XDRInPacketGetInt32(reply);
732 	st->st_size=XDRInPacketGetInt32(reply);
733 #if 0
734 	XDRInPacketGetInt32(reply);	// blksize
735 	st->st_blksize=NFS_MAXDATA;
736 #else
737 	st->st_blksize=XDRInPacketGetInt32(reply);
738 #endif
739 	st->st_rdev=XDRInPacketGetInt32(reply);
740 	XDRInPacketGetInt32(reply);	// blocks
741 	XDRInPacketGetInt32(reply);	// fsid
742 	st->st_ino=XDRInPacketGetInt32(reply);
743 	st->st_atime=XDRInPacketGetInt32(reply);
744 	XDRInPacketGetInt32(reply);	// usecs
745 	st->st_mtime=st->st_crtime=XDRInPacketGetInt32(reply);
746 	XDRInPacketGetInt32(reply);	// usecs
747 	st->st_ctime=XDRInPacketGetInt32(reply);
748 	XDRInPacketGetInt32(reply);	// usecs
749 }
750 
751 status_t map_nfs_to_system_error (status_t nfsstatus)
752 {
753 	switch (nfsstatus)
754 	{
755 		case NFS_OK:
756 			return B_OK;
757 
758 		case NFSERR_PERM:
759 			return EPERM;
760 
761 		case NFSERR_NOENT:
762 			return ENOENT;
763 
764 		case NFSERR_IO:
765 			return EIO;
766 
767 		case NFSERR_NXIO:
768 			return ENXIO;
769 
770 		case NFSERR_ACCES:
771 			return EACCES;
772 
773 		case NFSERR_EXIST:
774 			return EEXIST;
775 
776 		case NFSERR_NODEV:
777 			return ENODEV;
778 
779 		case NFSERR_NOTDIR:
780 			return ENOTDIR;
781 
782 		case NFSERR_ISDIR:
783 			return EISDIR;
784 
785 		case NFSERR_FBIG:
786 			return EFBIG;
787 
788 		case NFSERR_NOSPC:
789 			return ENOSPC;
790 
791 		case NFSERR_ROFS:
792 			return EROFS;
793 
794 		case NFSERR_NAMETOOLONG:
795 			return ENAMETOOLONG;
796 
797 		case NFSERR_NOTEMPTY:
798 			return ENOTEMPTY;
799 
800 		case NFSERR_STALE:
801 			return C_ERROR_STALE;
802 
803 		default:
804 			return B_ERROR;
805 	}
806 }
807 
808 extern nfs_fhandle
809 handle_from_vnid(fs_nspace *ns, vnode_id vnid)
810 {
811 	fs_node *current;
812 
813 	while (acquire_sem (ns->sem)==B_INTERRUPTED);
814 
815 	current=ns->first;
816 
817 	while ((current)&&(current->vnid!=vnid))
818 		current=current->next;
819 
820 	while (release_sem (ns->sem)==B_INTERRUPTED);
821 
822 	return current->fhandle;
823 }
824 
825 void insert_node (fs_nspace *ns, fs_node *node)
826 {
827 	fs_node *current;
828 
829 	while (acquire_sem (ns->sem)==B_INTERRUPTED);
830 
831 	current=ns->first;
832 
833 	while ((current)&&(current->vnid!=node->vnid))
834 		current=current->next;
835 
836 	if (current)
837 	{
838 		free(node);
839 		while (release_sem (ns->sem)==B_INTERRUPTED);
840 		return;
841 	}
842 
843 	node->next=ns->first;
844 	ns->first=node;
845 
846 	while (release_sem (ns->sem)==B_INTERRUPTED);
847 }
848 
849 void remove_node (fs_nspace *ns, vnode_id vnid)
850 {
851 	fs_node *current;
852 	fs_node *previous;
853 
854 	while(acquire_sem (ns->sem)==B_INTERRUPTED);
855 
856 	current=ns->first;
857 	previous=NULL;
858 
859 	while ((current)&&(current->vnid!=vnid))
860 	{
861 		previous=current;
862 		current=current->next;
863 	}
864 
865 	if (current)
866 	{
867 		if (previous)
868 			previous->next=current->next;
869 		else
870 			ns->first=current->next;
871 
872 		free(current);
873 	}
874 
875 	while (release_sem (ns->sem)==B_INTERRUPTED);
876 }
877 
878 extern int
879 fs_read_vnode(fs_nspace *ns, vnode_id vnid, char r, fs_node **node)
880 {
881 	fs_node *current;
882 
883 	if (!r)
884 	{
885 		while (acquire_sem (ns->sem)==B_INTERRUPTED);
886 	}
887 
888 	current=ns->first;
889 
890 	while ((current)&&(current->vnid!=vnid))
891 		current=current->next;
892 
893 	if (!current)
894 		return EINVAL;
895 
896 	*node=current;
897 
898 	if (!r)
899 	{
900 		while (release_sem (ns->sem)==B_INTERRUPTED);
901 	}
902 
903 	return B_OK;
904 }
905 
906 extern int
907 fs_write_vnode(fs_nspace *ns, fs_node *node, char r)
908 {
909 	return B_OK;
910 }
911 
912 extern int
913 fs_walk(fs_nspace *ns, fs_node *base, const char *file, char **newpath, vnode_id *vnid)
914 {
915 	bool isLink;
916 	fs_node *dummy;
917 	status_t result;
918 	//dprintf("nfs: walk(%s)\n", file);//XXX:mmu_man:debug
919 
920 	if (!strcmp(".",file))
921 	{
922 		*vnid=base->vnid;
923 		isLink=false;
924 	}
925 	else
926 	{
927 		fs_node *newNode=(fs_node *)malloc(sizeof(fs_node));
928 		struct stat st;
929 
930 		status_t result;
931 		if ((result=nfs_lookup(ns,&base->fhandle,file,&newNode->fhandle,&st))<B_OK)
932 		{
933 			free(newNode);
934 			return result;
935 		}
936 
937 		newNode->vnid=st.st_ino;
938 		*vnid=newNode->vnid;
939 
940 		insert_node (ns,newNode);
941 
942 		isLink=S_ISLNK(st.st_mode);
943 	}
944 
945 	if ((result=get_vnode (ns->nsid,*vnid,(void **)&dummy))<B_OK)
946 		return result;
947 
948 	if ((isLink)&&(newpath))
949 	{
950 		char path[NFS_MAXPATHLEN+1];
951 		size_t pathLen=NFS_MAXPATHLEN;
952 
953 		if ((result=fs_readlink(ns,dummy,path,&pathLen))<B_OK)
954 		{
955 			put_vnode (ns->nsid,*vnid);
956 			return result;
957 		}
958 
959 		path[pathLen]=0;
960 
961 		result=new_path(path,newpath);
962 
963 		if (result<B_OK)
964 		{
965 			put_vnode (ns->nsid,*vnid);
966 			return result;
967 		}
968 
969 		return put_vnode (ns->nsid,*vnid);
970 	}
971 
972 	return B_OK;
973 }
974 
975 extern int
976 fs_opendir(fs_nspace *ns, fs_node *node, nfs_cookie **cookie)
977 {
978 	struct stat st;
979 	nfs_fhandle fhandle;
980 
981 	status_t result;
982 	if ((result=nfs_getattr(ns,&node->fhandle,&st))<B_OK)
983 		return result;
984 
985 	if (!S_ISDIR(st.st_mode))
986 		return ENOTDIR;
987 
988 	*cookie=(nfs_cookie *)malloc(sizeof(nfs_cookie));
989 	memset ((*cookie)->opaque,0,NFS_COOKIESIZE);
990 
991 	return B_OK;
992 }
993 
994 extern int
995 fs_closedir(fs_nspace *ns, fs_node *node, nfs_cookie *cookie)
996 {
997 	return B_OK;
998 }
999 
1000 extern int
1001 fs_rewinddir(fs_nspace *ns, fs_node *node, nfs_cookie *cookie)
1002 {
1003 	memset (cookie->opaque,0,NFS_COOKIESIZE);
1004 
1005 	return B_OK;
1006 }
1007 
1008 extern int
1009 fs_readdir(fs_nspace *ns, fs_node *node, nfs_cookie *cookie, long *num, struct dirent *buf, size_t bufsize)
1010 {
1011 	int32 max=*num;
1012 	int32 eof;
1013 
1014 	size_t count=min_c(6000,max*300);
1015 
1016 	*num=0;
1017 
1018 	do
1019 	{
1020 		vnode_id vnid;
1021 		char *filename;
1022 		uint8 *replyBuf;
1023 		struct XDROutPacket call;
1024 		struct XDRInPacket reply;
1025 		int32 status;
1026 
1027 		XDROutPacketInit (&call);
1028 		XDRInPacketInit (&reply);
1029 
1030 		XDROutPacketAddFixed (&call,node->fhandle.opaque,NFS_FHSIZE);
1031 		XDROutPacketAddFixed (&call,cookie->opaque,NFS_COOKIESIZE);
1032 		XDROutPacketAddInt32 (&call,count);
1033 
1034 		replyBuf=send_rpc_call (ns,&ns->nfsAddr,NFS_PROGRAM,NFS_VERSION,NFSPROC_READDIR,&call);
1035 
1036 		if (!replyBuf)
1037 		{
1038 			XDRInPacketDestroy (&reply);
1039 			XDROutPacketDestroy (&call);
1040 			return B_ERROR;
1041 		}
1042 
1043 		XDRInPacketSetTo(&reply,replyBuf,0);
1044 
1045 		if (!is_successful_reply(&reply))
1046 		{
1047 			XDRInPacketDestroy (&reply);
1048 			XDROutPacketDestroy (&call);
1049 			return B_ERROR;
1050 		}
1051 
1052 		status=XDRInPacketGetInt32(&reply);
1053 
1054 		if (status!=NFS_OK)
1055 		{
1056 			XDRInPacketDestroy (&reply);
1057 			XDROutPacketDestroy (&call);
1058 			return map_nfs_to_system_error(status);
1059 		}
1060 
1061 		while (XDRInPacketGetInt32(&reply)==1)
1062 		{
1063 			nfs_cookie newCookie;
1064 
1065 			vnid=XDRInPacketGetInt32(&reply);
1066 			filename=XDRInPacketGetString(&reply);
1067 
1068 			XDRInPacketGetFixed(&reply,newCookie.opaque,NFS_COOKIESIZE);
1069 
1070 			//if (strcmp(".",filename)&&strcmp("..",filename))
1071 			//if ((ns->rootid != node->vnid) || (strcmp(".",filename)&&strcmp("..",filename)))
1072 			if (conf_ls_root_parent || ((ns->rootid != node->vnid) || strcmp("..",filename)))
1073 			{
1074 				status_t result;
1075 				struct stat st;
1076 
1077 				fs_node *newNode=(fs_node *)malloc(sizeof(fs_node));
1078 				newNode->vnid=vnid;
1079 
1080 				if ((result=nfs_lookup(ns,&node->fhandle,filename,&newNode->fhandle,&st))<B_OK)
1081 				{
1082 					free (filename);
1083 					free(newNode);
1084 					XDRInPacketDestroy (&reply);
1085 					XDROutPacketDestroy (&call);
1086 					return result;
1087 				}
1088 
1089 				insert_node (ns,newNode);
1090 
1091 				if (bufsize<2*(sizeof(dev_t)+sizeof(ino_t))+sizeof(unsigned short)+strlen(filename)+1)
1092 				{
1093 					XDRInPacketDestroy (&reply);
1094 					XDROutPacketDestroy (&call);
1095 					return B_OK;
1096 				}
1097 
1098 				buf->d_dev=ns->nsid;
1099 				buf->d_pdev=ns->nsid;
1100 				buf->d_ino=vnid;
1101 				buf->d_pino=node->vnid;
1102 				buf->d_reclen=2*(sizeof(dev_t)+sizeof(ino_t))+sizeof(unsigned short)+strlen(filename)+1;
1103 				strcpy (buf->d_name,filename);
1104 //				if ((ns->rootid == node->vnid))//XXX:mmu_man:test
1105 //					dprintf("nfs: dirent %d {d:%ld pd:%ld i:%lld pi:%lld '%s'}\n", *num, buf->d_dev, buf->d_pdev, buf->d_ino, buf->d_pino, buf->d_name);
1106 
1107 				bufsize-=buf->d_reclen;
1108 				buf=(struct dirent *)((char *)buf+buf->d_reclen);
1109 
1110 				memcpy (cookie->opaque,newCookie.opaque,NFS_COOKIESIZE);
1111 
1112 				(*num)++;
1113 			}
1114 			else {
1115 				memcpy (cookie->opaque,newCookie.opaque,NFS_COOKIESIZE);
1116 			}
1117 
1118 			free (filename);
1119 
1120 			if ((*num)==max)
1121 			{
1122 				XDRInPacketDestroy (&reply);
1123 				XDROutPacketDestroy (&call);
1124 				return B_OK;
1125 			}
1126 		}
1127 
1128 		eof=XDRInPacketGetInt32(&reply);
1129 
1130 		XDRInPacketDestroy (&reply);
1131 		XDROutPacketDestroy (&call);
1132 	}
1133 	while (eof==0);
1134 
1135 	return B_OK;
1136 }
1137 
1138 extern int
1139 fs_free_dircookie(fs_nspace *ns, fs_node *node, nfs_cookie *cookie)
1140 {
1141 	free(cookie);
1142 	return B_OK;
1143 }
1144 
1145 extern int
1146 fs_rstat(fs_nspace *ns, fs_node *node, struct stat *st)
1147 {
1148 	nfs_fhandle fhandle;
1149 
1150 	status_t result;
1151 	//dprintf("nfs: rstat()\n");//XXX:mmu_man:debug
1152 	if ((result=nfs_getattr(ns,&node->fhandle,st))<B_OK)
1153 		return result;
1154 
1155 	st->st_dev=ns->nsid;
1156 //st->st_nlink = 1; //XXX:mmu_man:test
1157 	return B_OK;
1158 }
1159 
1160 extern void
1161 fs_nspaceInit(struct fs_nspace *nspace)
1162 {
1163 	RPCPendingCallsInit (&nspace->pendingCalls);
1164 }
1165 
1166 extern void
1167 fs_nspaceDestroy(struct fs_nspace *nspace)
1168 {
1169 	RPCPendingCallsDestroy (&nspace->pendingCalls);
1170 }
1171 
1172 
1173 extern int
1174 fs_mount(nspace_id nsid, const char *devname, ulong flags, struct mount_nfs_params *parms, size_t len, fs_nspace **data, vnode_id *vnid)
1175 {
1176 	status_t result;
1177 	fs_nspace *ns;
1178 	fs_node *rootNode;
1179 	struct stat st;
1180 
1181 	if (parms==NULL)
1182 		return EINVAL;
1183 
1184 dprintf("nfs: mount(%d, %s, %08lx)\n", nsid, devname, flags);
1185 dprintf("nfs: nfs_params(ip:%lu, server:%s, export:%s, uid:%d, gid:%d, hostname:%s)\n",
1186         parms->serverIP,
1187         parms->server,
1188         parms->_export,
1189         parms->uid,
1190         parms->gid,
1191         parms->hostname);
1192 
1193 	if (!refcount)
1194 		read_config();
1195 
1196 	result = ksocket_init();
1197 	if (result < B_OK)
1198 		return result;
1199 
1200 	ns=(fs_nspace *)malloc(sizeof(fs_nspace));
1201 	fs_nspaceInit (ns);
1202 
1203 	ns->nsid=nsid;
1204 
1205 	ns->params.serverIP=parms->serverIP;
1206 	ns->params.server=strdup(parms->server);
1207 	ns->params._export=strdup(parms->_export);
1208 	ns->params.uid=parms->uid;
1209 	ns->params.gid=parms->gid;
1210 	ns->params.hostname=strdup(parms->hostname);
1211 	ns->xid=0;
1212 	ns->mountAddr.sin_family=AF_INET;
1213 	ns->mountAddr.sin_addr.s_addr=htonl(parms->serverIP);
1214 	memset (ns->mountAddr.sin_zero,0,sizeof(ns->mountAddr.sin_zero));
1215 
1216 
1217 	if ((result=create_socket(ns))<B_OK)
1218 	{
1219 		free (ns->params.hostname);
1220 		free (ns->params._export);
1221 		free (ns->params.server);
1222 
1223 		fs_nspaceDestroy (ns);
1224 		free(ns);
1225 
1226 		ksocket_cleanup();
1227 		return result;
1228 	}
1229 
1230 	if ((result=init_postoffice(ns))<B_OK)
1231 	{
1232 		kclosesocket(ns->s);
1233 		free (ns->params.hostname);
1234 		free (ns->params._export);
1235 		free (ns->params.server);
1236 
1237 		fs_nspaceDestroy (ns);
1238 		free(ns);
1239 
1240 		ksocket_cleanup();
1241 		return result;
1242 	}
1243 
1244 	if ((result=get_remote_address(ns,MOUNT_PROGRAM,MOUNT_VERSION,PMAP_IPPROTO_UDP,&ns->mountAddr))<B_OK)
1245 	{
1246 		shutdown_postoffice(ns);
1247 		free (ns->params.hostname);
1248 		free (ns->params._export);
1249 		free (ns->params.server);
1250 
1251 		fs_nspaceDestroy (ns);
1252 		free(ns);
1253 
1254 		ksocket_cleanup();
1255 		dprintf("nfs: error getting mountd address from portmapper: %s\n", strerror(result));
1256 		return result;
1257 	}
1258 
1259 	memcpy (&ns->nfsAddr,&ns->mountAddr,sizeof(ns->mountAddr));
1260 dprintf("nfs: mountd at %08lx:%d\n", ns->mountAddr.sin_addr.s_addr, ntohs(ns->mountAddr.sin_port));
1261 
1262 	if ((result=get_remote_address(ns,NFS_PROGRAM,NFS_VERSION,PMAP_IPPROTO_UDP,&ns->nfsAddr))<B_OK)
1263 	{
1264 		shutdown_postoffice(ns);
1265 		free (ns->params.hostname);
1266 		free (ns->params._export);
1267 		free (ns->params.server);
1268 
1269 		fs_nspaceDestroy (ns);
1270 		free(ns);
1271 
1272 		ksocket_cleanup();
1273 		dprintf("nfs: error getting nfsd address from portmapper: %s\n", strerror(result));
1274 		return result;
1275 	}
1276 dprintf("nfs: nfsd at %08lx:%d\n", ns->nfsAddr.sin_addr.s_addr, ntohs(ns->nfsAddr.sin_port));
1277 //	result = connect_socket(ns);
1278 //dprintf("nfs: connect: %s\n", strerror(result));
1279 
1280 	if ((result=create_sem(1,"nfs_sem"))<B_OK)
1281 	{
1282 		shutdown_postoffice(ns);
1283 		free (ns->params.hostname);
1284 		free (ns->params._export);
1285 		free (ns->params.server);
1286 
1287 		fs_nspaceDestroy (ns);
1288 		free(ns);
1289 
1290 		ksocket_cleanup();
1291 		return result;
1292 	}
1293 
1294 	ns->sem=result;
1295 
1296 	set_sem_owner (ns->sem,B_SYSTEM_TEAM);
1297 
1298 	rootNode=(fs_node *)malloc(sizeof(fs_node));
1299 	rootNode->next=NULL;
1300 
1301 	if ((result=nfs_mount(ns,ns->params._export,&rootNode->fhandle))<B_OK)
1302 	{
1303 		delete_sem (ns->sem);
1304 		free(rootNode);
1305 		shutdown_postoffice(ns);
1306 		free (ns->params.hostname);
1307 		free (ns->params._export);
1308 		free (ns->params.server);
1309 
1310 		fs_nspaceDestroy (ns);
1311 		free(ns);
1312 
1313 		ksocket_cleanup();
1314 		dprintf("nfs: error in nfs_mount: %s\n", strerror(result));
1315 		return result;
1316 	}
1317 
1318 	if ((result=nfs_getattr(ns,&rootNode->fhandle,&st))<B_OK)
1319 	{
1320 		delete_sem (ns->sem);
1321 		free(rootNode);
1322 		shutdown_postoffice(ns);
1323 		free (ns->params.hostname);
1324 		free (ns->params._export);
1325 		free (ns->params.server);
1326 
1327 		fs_nspaceDestroy (ns);
1328 		free(ns);
1329 
1330 		ksocket_cleanup();
1331 		return result;
1332 	}
1333 
1334 	ns->rootid=st.st_ino;
1335 	rootNode->vnid=ns->rootid;
1336 
1337 	*vnid=ns->rootid;
1338 
1339 	if ((result=new_vnode(nsid,*vnid,rootNode))<B_OK)
1340 	{
1341 		delete_sem (ns->sem);
1342 		free(rootNode);
1343 		shutdown_postoffice(ns);
1344 		free (ns->params.hostname);
1345 		free (ns->params._export);
1346 		free (ns->params.server);
1347 
1348 		fs_nspaceDestroy (ns);
1349 		free(ns);
1350 
1351 		ksocket_cleanup();
1352 		return result;
1353 	}
1354 
1355 	*data=ns;
1356 
1357 	ns->first=rootNode;
1358 
1359 	return B_OK;
1360 }
1361 
1362 extern int
1363 fs_unmount(fs_nspace *ns)
1364 {
1365 	free (ns->params.hostname);
1366 	free (ns->params._export);
1367 	free (ns->params.server);
1368 
1369 	while (ns->first)
1370 	{
1371 		fs_node *next=ns->first->next;
1372 		free(ns->first);
1373 		ns->first=next;
1374 	}
1375 
1376 	delete_sem (ns->sem);
1377 	shutdown_postoffice(ns);
1378 	fs_nspaceDestroy (ns);
1379 	free(ns);
1380 	ksocket_cleanup();
1381 	return B_OK;
1382 }
1383 
1384 extern int
1385 fs_rfsstat(fs_nspace *ns, struct fs_info *info)
1386 {
1387 	struct XDROutPacket call;
1388 	struct XDRInPacket reply;
1389 	nfs_fhandle rootHandle=handle_from_vnid (ns,ns->rootid);
1390 	uint8 *replyBuf;
1391 	int32 status;
1392 	//dprintf("nfs: rfsstat()\n");//XXX:mmu_man:debug
1393 
1394 	XDROutPacketInit (&call);
1395 	XDRInPacketInit (&reply);
1396 
1397 	XDROutPacketAddFixed (&call,rootHandle.opaque,NFS_FHSIZE);
1398 
1399 	replyBuf=send_rpc_call (ns,&ns->nfsAddr,NFS_PROGRAM,NFS_VERSION,NFSPROC_STATFS,&call);
1400 
1401 	if (!replyBuf)
1402 	{
1403 		XDRInPacketDestroy (&reply);
1404 		XDROutPacketDestroy (&call);
1405 		return EHOSTUNREACH;
1406 	}
1407 
1408 	XDRInPacketSetTo(&reply,replyBuf,0);
1409 
1410 	if (!is_successful_reply(&reply))
1411 	{
1412 		XDRInPacketDestroy (&reply);
1413 		XDROutPacketDestroy (&call);
1414 		return B_ERROR;
1415 	}
1416 
1417 	status=XDRInPacketGetInt32(&reply);
1418 
1419 	if (status!=NFS_OK)
1420 	{
1421 		XDRInPacketDestroy (&reply);
1422 		XDROutPacketDestroy (&call);
1423 		//dprintf("nfs: rfsstat() error 0x%08lx\n", map_nfs_to_system_error(status));
1424 		return map_nfs_to_system_error(status);
1425 	}
1426 
1427 	info->dev=ns->nsid;
1428 	info->root=ns->rootid;
1429 	info->flags=NFS_FS_FLAGS;
1430 
1431 	XDRInPacketGetInt32(&reply);	// tsize
1432 
1433 	info->block_size=XDRInPacketGetInt32(&reply);
1434 	info->io_size=8192;
1435 	info->total_blocks=XDRInPacketGetInt32(&reply);
1436 	info->free_blocks=XDRInPacketGetInt32(&reply);
1437 	info->total_nodes=100;
1438 	info->free_nodes=100;
1439 	//strcpy (info->device_name,"nfs_device");
1440 	strcpy (info->device_name,"");
1441 	strcpy (info->volume_name,"nfs://");
1442 	strcat (info->volume_name,ns->params.server);
1443 	strcat (info->volume_name,ns->params._export);
1444 	//strcpy (info->fsh_name,"nfs_fsh");
1445 	strcpy (info->fsh_name,"nfs");
1446 
1447 	XDRInPacketDestroy (&reply);
1448 	XDROutPacketDestroy (&call);
1449 	return B_OK;
1450 }
1451 
1452 extern int
1453 fs_open(fs_nspace *ns, fs_node *node, int omode, fs_file_cookie **cookie)
1454 {
1455 	struct stat st;
1456 	nfs_fhandle fhandle;
1457 
1458 	status_t result;
1459 	if ((result=nfs_getattr(ns,&node->fhandle,&st))<B_OK)
1460 		return result;
1461 
1462 	if (S_ISDIR(st.st_mode)) {
1463 		/* permit opening of directories */
1464 		if (conf_allow_dir_open) {
1465 			*cookie = NULL;
1466 			return B_OK;
1467 		} else
1468 			return EISDIR;
1469 	}
1470 
1471 	*cookie=(fs_file_cookie *)malloc(sizeof(fs_file_cookie));
1472 	(*cookie)->omode=omode;
1473 	(*cookie)->original_size=st.st_size;
1474 	(*cookie)->st=st;
1475 
1476 	return B_OK;
1477 }
1478 
1479 extern int
1480 fs_close(fs_nspace *ns, fs_node *node, fs_file_cookie *cookie)
1481 {
1482 /*	//XXX:mmu_man:why that ?? makes Tracker go nuts updating the stats
1483 	if ((cookie->omode & O_RDWR)||(cookie->omode & O_WRONLY))
1484 		return my_notify_listener (B_STAT_CHANGED,ns->nsid,0,0,node->vnid,NULL);
1485 */
1486 	return B_OK;
1487 }
1488 
1489 extern int
1490 fs_free_cookie(fs_nspace *ns, fs_node *node, fs_file_cookie *cookie)
1491 {
1492 	if (cookie)
1493 		free(cookie);
1494 	return B_OK;
1495 }
1496 
1497 extern int
1498 fs_read(fs_nspace *ns, fs_node *node, fs_file_cookie *cookie, off_t pos, void *buf, size_t *len)
1499 {
1500 	size_t max=*len;
1501 	*len=0;
1502 
1503 	if (!cookie) return EISDIR; /* do not permit reading of directories */
1504 	while ((*len)<max)
1505 	{
1506 		size_t count=min_c(NFS_MAXDATA,max-(*len));
1507 
1508 		struct XDROutPacket call;
1509 		struct XDRInPacket reply;
1510 
1511 		int32 status;
1512 		uint8 *replyBuf;
1513 
1514 		struct stat st;
1515 		size_t readbytes;
1516 
1517 		XDROutPacketInit (&call);
1518 		XDRInPacketInit (&reply);
1519 
1520 		XDROutPacketAddFixed (&call,&node->fhandle.opaque,NFS_FHSIZE);
1521 		XDROutPacketAddInt32 (&call,pos);
1522 		XDROutPacketAddInt32 (&call,count);
1523 		XDROutPacketAddInt32 (&call,0);
1524 
1525 		replyBuf=send_rpc_call (ns,&ns->nfsAddr,NFS_PROGRAM,NFS_VERSION,NFSPROC_READ,&call);
1526 
1527 		if (!replyBuf)
1528 		{
1529 			XDRInPacketDestroy (&reply);
1530 			XDROutPacketDestroy (&call);
1531 			return B_ERROR;
1532 		}
1533 
1534 		XDRInPacketSetTo(&reply,replyBuf,0);
1535 
1536 		if (!is_successful_reply(&reply))
1537 		{
1538 			XDRInPacketDestroy (&reply);
1539 			XDROutPacketDestroy (&call);
1540 			return B_ERROR;
1541 		}
1542 
1543 		status=XDRInPacketGetInt32(&reply);
1544 
1545 		if (status!=NFS_OK)
1546 		{
1547 			XDRInPacketDestroy (&reply);
1548 			XDROutPacketDestroy (&call);
1549 			return map_nfs_to_system_error(status);
1550 		}
1551 
1552 		get_nfs_attr (&reply,&st);
1553 
1554 		cookie->st=st;
1555 
1556 		readbytes=XDRInPacketGetDynamic(&reply,buf);
1557 
1558 		buf=(char *)buf+readbytes;
1559 		(*len)+=readbytes;
1560 		pos+=readbytes;
1561 
1562 		if (pos>=st.st_size)
1563 		{
1564 			XDRInPacketDestroy (&reply);
1565 			XDROutPacketDestroy (&call);
1566 			break;
1567 		}
1568 
1569 		XDRInPacketDestroy (&reply);
1570 		XDROutPacketDestroy (&call);
1571 	}
1572 
1573 	return B_OK;
1574 }
1575 
1576 extern int
1577 fs_write(fs_nspace *ns, fs_node *node, fs_file_cookie *cookie, off_t pos, const void *buf, size_t *len)
1578 {
1579 	size_t bytesWritten=0;
1580 
1581 	if (!cookie) return EISDIR; /* do not permit reading of directories */
1582 	if (cookie->omode & O_APPEND)
1583 		pos+=cookie->original_size;
1584 
1585 	while (bytesWritten<*len)
1586 	{
1587 		size_t count=min_c(NFS_MAXDATA,(*len)-bytesWritten);
1588 
1589 		struct XDROutPacket call;
1590 		struct XDRInPacket reply;
1591 		int32 status;
1592 		uint8 *replyBuf;
1593 		struct stat st;
1594 
1595 		XDROutPacketInit (&call);
1596 		XDRInPacketInit (&reply);
1597 
1598 		XDROutPacketAddFixed (&call,&node->fhandle.opaque,NFS_FHSIZE);
1599 		XDROutPacketAddInt32 (&call,0);
1600 		XDROutPacketAddInt32 (&call,pos+bytesWritten);
1601 		XDROutPacketAddInt32 (&call,0);
1602 		XDROutPacketAddDynamic (&call,(const char *)buf+bytesWritten,count);
1603 
1604 		replyBuf=send_rpc_call (ns,&ns->nfsAddr,NFS_PROGRAM,NFS_VERSION,NFSPROC_WRITE,&call);
1605 
1606 		if (!replyBuf)
1607 		{
1608 			XDRInPacketDestroy (&reply);
1609 			XDROutPacketDestroy (&call);
1610 			return B_ERROR;
1611 		}
1612 
1613 		XDRInPacketSetTo (&reply,replyBuf,0);
1614 
1615 		if (!is_successful_reply(&reply))
1616 		{
1617 			XDRInPacketDestroy (&reply);
1618 			XDROutPacketDestroy (&call);
1619 			return B_ERROR;
1620 		}
1621 
1622 		status=XDRInPacketGetInt32(&reply);
1623 
1624 		if (status!=NFS_OK)
1625 		{
1626 			XDRInPacketDestroy (&reply);
1627 			XDROutPacketDestroy (&call);
1628 			return map_nfs_to_system_error(status);
1629 		}
1630 
1631 		get_nfs_attr (&reply,&st);
1632 
1633 		cookie->st=st;
1634 
1635 		bytesWritten+=count;
1636 
1637 		XDRInPacketDestroy (&reply);
1638 		XDROutPacketDestroy (&call);
1639 	}
1640 
1641 	return B_OK;
1642 }
1643 
1644 extern int
1645 fs_wstat(fs_nspace *ns, fs_node *node, struct stat *st, long mask)
1646 {
1647 	struct XDROutPacket call;
1648 	struct XDRInPacket reply;
1649 
1650 	uint8 *replyBuf;
1651 	int32 status;
1652 
1653 	XDROutPacketInit (&call);
1654 	XDRInPacketInit (&reply);
1655 
1656 	XDROutPacketAddFixed (&call,node->fhandle.opaque,NFS_FHSIZE);
1657 
1658 	XDROutPacketAddInt32 (&call,(mask & WSTAT_MODE) ? st->st_mode : -1);
1659 	XDROutPacketAddInt32 (&call,(mask & WSTAT_UID) ? st->st_uid : -1);
1660 	XDROutPacketAddInt32 (&call,(mask & WSTAT_GID) ? st->st_gid : -1);
1661 	XDROutPacketAddInt32 (&call,(mask & WSTAT_SIZE) ? st->st_size : -1);
1662 	XDROutPacketAddInt32 (&call,(mask & WSTAT_ATIME) ? st->st_atime : -1);
1663 	XDROutPacketAddInt32 (&call,(mask & WSTAT_ATIME) ? 0 : -1);
1664 	XDROutPacketAddInt32 (&call,(mask & WSTAT_MTIME) ? st->st_mtime : -1);
1665 	XDROutPacketAddInt32 (&call,(mask & WSTAT_MTIME) ? 0 : -1);
1666 
1667 	replyBuf=send_rpc_call (ns,&ns->nfsAddr,NFS_PROGRAM,NFS_VERSION,NFSPROC_SETATTR,&call);
1668 
1669 	if (!replyBuf)
1670 	{
1671 		XDRInPacketDestroy (&reply);
1672 		XDROutPacketDestroy (&call);
1673 		return EHOSTUNREACH;
1674 	}
1675 
1676 	XDRInPacketSetTo (&reply,replyBuf,0);
1677 
1678 	if (!is_successful_reply(&reply))
1679 	{
1680 		XDRInPacketDestroy (&reply);
1681 		XDROutPacketDestroy (&call);
1682 		return B_ERROR;
1683 	}
1684 
1685 	status=XDRInPacketGetInt32(&reply);
1686 
1687 	if (status!=NFS_OK)
1688 		return map_nfs_to_system_error(status);
1689 
1690 	XDRInPacketDestroy (&reply);
1691 	XDROutPacketDestroy (&call);
1692 	return my_notify_listener (B_STAT_CHANGED,ns->nsid,0,0,node->vnid,NULL);
1693 }
1694 
1695 extern int
1696 fs_wfsstat(fs_nspace *ns, struct fs_info *info, long mask)
1697 {
1698 	return B_OK;
1699 }
1700 
1701 extern int
1702 fs_create(fs_nspace *ns, fs_node *dir, const char *name, int omode, int perms, vnode_id *vnid,
1703 					fs_file_cookie **cookie)
1704 {
1705 	nfs_fhandle fhandle;
1706 	struct stat st;
1707 
1708 	status_t result;
1709 	result=nfs_lookup(ns,&dir->fhandle,name,&fhandle,&st);
1710 
1711 	if (result==B_OK)
1712 	{
1713 		void *dummy;
1714 		fs_node *newNode=(fs_node *)malloc(sizeof(fs_node));
1715 		newNode->fhandle=fhandle;
1716 		newNode->vnid=st.st_ino;
1717 		insert_node (ns,newNode);
1718 
1719 		*vnid=st.st_ino;
1720 
1721 		if ((result=get_vnode(ns->nsid,*vnid,&dummy))<B_OK)
1722 			return result;
1723 
1724 		if (S_ISDIR(st.st_mode))
1725 			return EISDIR;
1726 
1727 		if (omode & O_EXCL)
1728 			return EEXIST;
1729 
1730 		if (omode & O_TRUNC)
1731 		{
1732 			if ((result=nfs_truncate_file(ns,&fhandle,NULL))<B_OK)
1733 				return result;
1734 		}
1735 
1736 		*cookie=(fs_file_cookie *)malloc(sizeof(fs_file_cookie));
1737 		(*cookie)->omode=omode;
1738 		(*cookie)->original_size=st.st_size;
1739 		(*cookie)->st=st;
1740 
1741 		return B_OK;
1742 	}
1743 	else if (result!=ENOENT)
1744 		return result;
1745 	else
1746 	{
1747 		struct XDROutPacket call;
1748 		struct XDRInPacket reply;
1749 
1750 		uint8 *replyBuf;
1751 		int32 status;
1752 
1753 		fs_node *newNode;
1754 
1755 		if (!(omode & O_CREAT))
1756 			return ENOENT;
1757 
1758 		XDROutPacketInit (&call);
1759 		XDRInPacketInit (&reply);
1760 
1761 		XDROutPacketAddFixed (&call,dir->fhandle.opaque,NFS_FHSIZE);
1762 		XDROutPacketAddString(&call,name);
1763 		XDROutPacketAddInt32 (&call,perms|S_IFREG);
1764 		XDROutPacketAddInt32 (&call,-1);
1765 		XDROutPacketAddInt32 (&call,-1);
1766 		XDROutPacketAddInt32 (&call,0);
1767 		XDROutPacketAddInt32 (&call,time(NULL));
1768 		XDROutPacketAddInt32 (&call,0);
1769 		XDROutPacketAddInt32 (&call,time(NULL));
1770 		XDROutPacketAddInt32 (&call,0);
1771 
1772 		replyBuf=send_rpc_call (ns,&ns->nfsAddr,NFS_PROGRAM,NFS_VERSION,NFSPROC_CREATE,&call);
1773 
1774 		if (!replyBuf)
1775 		{
1776 			XDRInPacketDestroy (&reply);
1777 			XDROutPacketDestroy (&call);
1778 			return B_ERROR;
1779 		}
1780 
1781 		XDRInPacketSetTo (&reply,replyBuf,0);
1782 
1783 		if (!is_successful_reply(&reply))
1784 		{
1785 			XDRInPacketDestroy (&reply);
1786 			XDROutPacketDestroy (&call);
1787 			return B_ERROR;
1788 		}
1789 
1790 		status=XDRInPacketGetInt32(&reply);
1791 
1792 		if (status!=NFS_OK)
1793 		{
1794 			XDRInPacketDestroy (&reply);
1795 			XDROutPacketDestroy (&call);
1796 			return map_nfs_to_system_error(status);
1797 		}
1798 
1799 		XDRInPacketGetFixed (&reply,fhandle.opaque,NFS_FHSIZE);
1800 
1801 		get_nfs_attr (&reply,&st);
1802 
1803 		newNode=(fs_node *)malloc(sizeof(fs_node));
1804 		newNode->fhandle=fhandle;
1805 		newNode->vnid=st.st_ino;
1806 
1807 		insert_node (ns,newNode);
1808 
1809 		*vnid=st.st_ino;
1810 		*cookie=(fs_file_cookie *)malloc(sizeof(fs_file_cookie));
1811 		(*cookie)->omode=omode;
1812 		(*cookie)->original_size=st.st_size;
1813 		(*cookie)->st=st;
1814 
1815 		result=new_vnode (ns->nsid,*vnid,newNode);
1816 
1817 		if (result<B_OK)
1818 		{
1819 			XDRInPacketDestroy (&reply);
1820 			XDROutPacketDestroy (&call);
1821 			return result;
1822 		}
1823 
1824 		XDRInPacketDestroy (&reply);
1825 		XDROutPacketDestroy (&call);
1826 		return my_notify_listener (B_ENTRY_CREATED,ns->nsid,dir->vnid,0,*vnid,name);
1827 	}
1828 }
1829 
1830 extern int
1831 fs_unlink(fs_nspace *ns, fs_node *dir, const char *name)
1832 {
1833 	status_t result;
1834 	fs_node *newNode;
1835 	fs_node *dummy;
1836 
1837 	struct XDROutPacket call;
1838 	struct XDRInPacket reply;
1839 
1840 	struct stat st;
1841 	nfs_fhandle fhandle;
1842 	uint8 *replyBuf;
1843 
1844 	int32 status;
1845 
1846 	XDROutPacketInit (&call);
1847 	XDRInPacketInit (&reply);
1848 
1849 	if ((result=nfs_lookup(ns,&dir->fhandle,name,&fhandle,&st))<B_OK)
1850 	{
1851 		XDRInPacketDestroy (&reply);
1852 		XDROutPacketDestroy (&call);
1853 		return result;
1854 	}
1855 
1856 	newNode=(fs_node *)malloc(sizeof(fs_node));
1857 	newNode->fhandle=fhandle;
1858 	newNode->vnid=st.st_ino;
1859 
1860 	insert_node (ns,newNode);
1861 
1862 	if ((result=get_vnode(ns->nsid,st.st_ino,(void **)&dummy))<B_OK)
1863 	{
1864 		XDRInPacketDestroy (&reply);
1865 		XDROutPacketDestroy (&call);
1866 		return result;
1867 	}
1868 
1869 	if (!S_ISREG(st.st_mode)&&!S_ISLNK(st.st_mode))
1870 	{
1871 		XDRInPacketDestroy (&reply);
1872 		XDROutPacketDestroy (&call);
1873 		return EISDIR;
1874 	}
1875 
1876 	if ((result=remove_vnode(ns->nsid,st.st_ino))<B_OK)
1877 	{
1878 		XDRInPacketDestroy (&reply);
1879 		XDROutPacketDestroy (&call);
1880 		return result;
1881 	}
1882 
1883 	if ((result=put_vnode(ns->nsid,st.st_ino))<B_OK)
1884 	{
1885 		XDRInPacketDestroy (&reply);
1886 		XDROutPacketDestroy (&call);
1887 		return result;
1888 	}
1889 
1890 	XDROutPacketAddFixed (&call,dir->fhandle.opaque,NFS_FHSIZE);
1891 	XDROutPacketAddString(&call,name);
1892 
1893 	replyBuf=send_rpc_call (ns,&ns->nfsAddr,NFS_PROGRAM,NFS_VERSION,NFSPROC_REMOVE,&call);
1894 
1895 	if (!replyBuf)
1896 	{
1897 		XDRInPacketDestroy (&reply);
1898 		XDROutPacketDestroy (&call);
1899 		return EHOSTUNREACH;
1900 	}
1901 
1902 	XDRInPacketSetTo(&reply,replyBuf,0);
1903 
1904 	if (!is_successful_reply(&reply))
1905 	{
1906 		XDRInPacketDestroy (&reply);
1907 		XDROutPacketDestroy (&call);
1908 		return B_ERROR;
1909 	}
1910 
1911 	status=XDRInPacketGetInt32(&reply);
1912 
1913 	if (status!=NFS_OK)
1914 	{
1915 		XDRInPacketDestroy (&reply);
1916 		XDROutPacketDestroy (&call);
1917 		return map_nfs_to_system_error(status);
1918 	}
1919 
1920 	XDRInPacketDestroy (&reply);
1921 	XDROutPacketDestroy (&call);
1922 
1923 	return my_notify_listener (B_ENTRY_REMOVED,ns->nsid,dir->vnid,0,st.st_ino,name);
1924 }
1925 
1926 extern int
1927 fs_remove_vnode(fs_nspace *ns, fs_node *node, char r)
1928 {
1929 	remove_node (ns,node->vnid);
1930 
1931 	return B_OK;
1932 }
1933 
1934 extern int
1935 fs_secure_vnode(fs_nspace *ns, fs_node *node)
1936 {
1937 	return B_OK;
1938 }
1939 
1940 extern int
1941 fs_mkdir(fs_nspace *ns, fs_node *dir, const char *name, int perms)
1942 {
1943 	nfs_fhandle fhandle;
1944 	struct stat st;
1945 	fs_node *newNode;
1946 
1947 	status_t result;
1948 	uint8 *replyBuf;
1949 	int32 status;
1950 
1951 	struct XDROutPacket call;
1952 	struct XDRInPacket reply;
1953 
1954 	XDROutPacketInit (&call);
1955 	XDRInPacketInit (&reply);
1956 
1957 	result=nfs_lookup(ns,&dir->fhandle,name,&fhandle,&st);
1958 
1959 	if (result==B_OK)
1960 	{
1961 		void *dummy;
1962 		if ((result=get_vnode(ns->nsid,st.st_ino,&dummy))<B_OK)
1963 			return result;
1964 
1965 		XDRInPacketDestroy (&reply);
1966 		XDROutPacketDestroy (&call);
1967 		return EEXIST;
1968 	}
1969 	else if (result!=ENOENT)
1970 	{
1971 		XDRInPacketDestroy (&reply);
1972 		XDROutPacketDestroy (&call);
1973 		return result;
1974 	}
1975 
1976 	XDROutPacketAddFixed (&call,dir->fhandle.opaque,NFS_FHSIZE);
1977 	XDROutPacketAddString(&call,name);
1978 	XDROutPacketAddInt32 (&call,perms|S_IFDIR);
1979 	XDROutPacketAddInt32 (&call,-1);
1980 	XDROutPacketAddInt32 (&call,-1);
1981 	XDROutPacketAddInt32 (&call,-1);
1982 	XDROutPacketAddInt32 (&call,time(NULL));
1983 	XDROutPacketAddInt32 (&call,0);
1984 	XDROutPacketAddInt32 (&call,time(NULL));
1985 	XDROutPacketAddInt32 (&call,0);
1986 
1987 	replyBuf=send_rpc_call (ns,&ns->nfsAddr,NFS_PROGRAM,NFS_VERSION,NFSPROC_MKDIR,&call);
1988 
1989 	if (!replyBuf)
1990 	{
1991 		XDRInPacketDestroy (&reply);
1992 		XDROutPacketDestroy (&call);
1993 		return B_ERROR;
1994 	}
1995 
1996 	XDRInPacketSetTo (&reply,replyBuf,0);
1997 
1998 	if (!is_successful_reply(&reply))
1999 	{
2000 		XDRInPacketDestroy (&reply);
2001 		XDROutPacketDestroy (&call);
2002 		return B_ERROR;
2003 	}
2004 
2005 	status=XDRInPacketGetInt32(&reply);
2006 
2007 	if (status!=NFS_OK)
2008 	{
2009 		XDROutPacketDestroy (&call);
2010 		return map_nfs_to_system_error(status);
2011 	}
2012 
2013 	XDRInPacketGetFixed(&reply,fhandle.opaque,NFS_FHSIZE);
2014 
2015 	get_nfs_attr (&reply,&st);
2016 
2017 	newNode=(fs_node *)malloc(sizeof(fs_node));
2018 	newNode->fhandle=fhandle;
2019 	newNode->vnid=st.st_ino;
2020 
2021 	insert_node (ns,newNode);
2022 
2023 	XDRInPacketDestroy (&reply);
2024 	XDROutPacketDestroy (&call);
2025 
2026 	return my_notify_listener (B_ENTRY_CREATED,ns->nsid,dir->vnid,0,st.st_ino,name);
2027 }
2028 
2029 extern int
2030 fs_rename(fs_nspace *ns, fs_node *olddir, const char *oldname, fs_node *newdir, const char *newname)
2031 {
2032 	struct stat st;
2033 	nfs_fhandle fhandle;
2034 	status_t result;
2035 	struct XDROutPacket call;
2036 	struct XDRInPacket reply;
2037 	int32 status;
2038 	uint8 *replyBuf;
2039 
2040 	XDROutPacketInit (&call);
2041 	XDRInPacketInit (&reply);
2042 
2043 	if ((result=nfs_lookup(ns,&newdir->fhandle,newname,&fhandle,&st))==B_OK)
2044 	{
2045 		if (S_ISREG(st.st_mode))
2046 			result=fs_unlink (ns,newdir,newname);
2047 		else
2048 			result=fs_rmdir (ns,newdir,newname);
2049 
2050 		if (result<B_OK)
2051 		{
2052 			XDRInPacketDestroy (&reply);
2053 			XDROutPacketDestroy (&call);
2054 			return result;
2055 		}
2056 	}
2057 
2058 	if ((result=nfs_lookup(ns,&olddir->fhandle,oldname,&fhandle,&st))<B_OK)
2059 	{
2060 		XDRInPacketDestroy (&reply);
2061 		XDROutPacketDestroy (&call);
2062 		return result;
2063 	}
2064 
2065 	XDROutPacketAddFixed (&call,olddir->fhandle.opaque,NFS_FHSIZE);
2066 	XDROutPacketAddString(&call,oldname);
2067 	XDROutPacketAddFixed (&call,newdir->fhandle.opaque,NFS_FHSIZE);
2068 	XDROutPacketAddString(&call,newname);
2069 
2070 	replyBuf=send_rpc_call (ns,&ns->nfsAddr,NFS_PROGRAM,NFS_VERSION,NFSPROC_RENAME,&call);
2071 
2072 	if (!replyBuf)
2073 	{
2074 		XDRInPacketDestroy (&reply);
2075 		XDROutPacketDestroy (&call);
2076 		return EHOSTUNREACH;
2077 	}
2078 
2079 	XDRInPacketSetTo (&reply,replyBuf,0);
2080 
2081 	if (!is_successful_reply(&reply))
2082 	{
2083 		XDRInPacketDestroy (&reply);
2084 		XDROutPacketDestroy (&call);
2085 		return B_ERROR;
2086 	}
2087 
2088 	status=XDRInPacketGetInt32(&reply);
2089 
2090 	if (status!=NFS_OK)
2091 	{
2092 		XDRInPacketDestroy (&reply);
2093 		XDROutPacketDestroy (&call);
2094 		return map_nfs_to_system_error(status);
2095 	}
2096 
2097 	XDRInPacketDestroy (&reply);
2098 	XDROutPacketDestroy (&call);
2099 
2100 	return my_notify_listener (B_ENTRY_MOVED,ns->nsid,olddir->vnid,newdir->vnid,st.st_ino,newname);
2101 }
2102 
2103 extern int
2104 fs_rmdir(fs_nspace *ns, fs_node *dir, const char *name)
2105 {
2106 	status_t result;
2107 	fs_node *newNode;
2108 	fs_node *dummy;
2109 	struct XDROutPacket call;
2110 	struct XDRInPacket reply;
2111 	int32 status;
2112 	uint8 *replyBuf;
2113 
2114 	struct stat st;
2115 	nfs_fhandle fhandle;
2116 
2117 	XDROutPacketInit(&call);
2118 	XDRInPacketInit(&reply);
2119 
2120 	if ((result=nfs_lookup(ns,&dir->fhandle,name,&fhandle,&st))<B_OK)
2121 	{
2122 		XDRInPacketDestroy(&reply);
2123 		XDROutPacketDestroy(&call);
2124 		return result;
2125 	}
2126 
2127 	newNode=(fs_node *)malloc(sizeof(fs_node));
2128 	newNode->fhandle=fhandle;
2129 	newNode->vnid=st.st_ino;
2130 
2131 	insert_node (ns,newNode);
2132 
2133 	if ((result=get_vnode(ns->nsid,st.st_ino,(void **)&dummy))<B_OK)
2134 	{
2135 		XDRInPacketDestroy(&reply);
2136 		XDROutPacketDestroy(&call);
2137 		return result;
2138 	}
2139 
2140 	if (!S_ISDIR(st.st_mode))
2141 	{
2142 		XDRInPacketDestroy(&reply);
2143 		XDROutPacketDestroy(&call);
2144 		return ENOTDIR;
2145 	}
2146 
2147 	if ((result=remove_vnode(ns->nsid,st.st_ino))<B_OK)
2148 	{
2149 		XDRInPacketDestroy(&reply);
2150 		XDROutPacketDestroy(&call);
2151 		return result;
2152 	}
2153 
2154 	if ((result=put_vnode(ns->nsid,st.st_ino))<B_OK)
2155 	{
2156 		XDRInPacketDestroy(&reply);
2157 		XDROutPacketDestroy(&call);
2158 		return result;
2159 	}
2160 
2161 	XDROutPacketAddFixed (&call,dir->fhandle.opaque,NFS_FHSIZE);
2162 	XDROutPacketAddString(&call,name);
2163 
2164 	replyBuf=send_rpc_call (ns,&ns->nfsAddr,NFS_PROGRAM,NFS_VERSION,NFSPROC_RMDIR,&call);
2165 
2166 	if (!replyBuf)
2167 	{
2168 		XDRInPacketDestroy(&reply);
2169 		XDROutPacketDestroy(&call);
2170 		return EHOSTUNREACH;
2171 	}
2172 
2173 	XDRInPacketSetTo (&reply,replyBuf,0);
2174 
2175 	if (!is_successful_reply(&reply))
2176 	{
2177 		XDRInPacketDestroy(&reply);
2178 		XDROutPacketDestroy(&call);
2179 		return B_ERROR;
2180 	}
2181 
2182 	status=XDRInPacketGetInt32(&reply);
2183 
2184 	if (status!=NFS_OK)
2185 	{
2186 		XDRInPacketDestroy(&reply);
2187 		XDROutPacketDestroy(&call);
2188 		return map_nfs_to_system_error(status);
2189 	}
2190 
2191 	XDRInPacketDestroy(&reply);
2192 	XDROutPacketDestroy(&call);
2193 	return my_notify_listener (B_ENTRY_REMOVED,ns->nsid,dir->vnid,0,st.st_ino,name);
2194 }
2195 
2196 extern int
2197 fs_readlink(fs_nspace *ns, fs_node *node, char *buf, size_t *bufsize)
2198 {
2199 	struct XDROutPacket call;
2200 	uint8 *replyBuf;
2201 	int32 status;
2202 	size_t length;
2203 	char data[NFS_MAXPATHLEN];
2204 	struct XDRInPacket reply;
2205 
2206 	XDROutPacketInit (&call);
2207 	XDRInPacketInit(&reply);
2208 
2209 	XDROutPacketAddFixed (&call,node->fhandle.opaque,NFS_FHSIZE);
2210 
2211 	replyBuf=send_rpc_call (ns,&ns->nfsAddr,NFS_PROGRAM,NFS_VERSION,NFSPROC_READLINK,&call);
2212 
2213 	if (!replyBuf)
2214 	{
2215 		XDRInPacketDestroy(&reply);
2216 		XDROutPacketDestroy (&call);
2217 		return EHOSTUNREACH;
2218 	}
2219 
2220 	XDRInPacketSetTo (&reply,replyBuf,0);
2221 
2222 	if (!is_successful_reply(&reply))
2223 	{
2224 		XDRInPacketDestroy(&reply);
2225 		XDROutPacketDestroy (&call);
2226 		return B_ERROR;
2227 	}
2228 
2229 	status=XDRInPacketGetInt32(&reply);
2230 
2231 	if (status!=NFS_OK)
2232 	{
2233 		XDRInPacketDestroy(&reply);
2234 		XDROutPacketDestroy (&call);
2235 		return map_nfs_to_system_error(status);
2236 	}
2237 
2238 	length=XDRInPacketGetDynamic(&reply,data);
2239 
2240 	length=min_c(length,*bufsize);
2241 	memcpy (buf,data,length);
2242 	*bufsize=length;
2243 
2244 	XDRInPacketDestroy(&reply);
2245 	XDROutPacketDestroy (&call);
2246 	return B_OK;
2247 }
2248 
2249 extern int
2250 fs_symlink(fs_nspace *ns, fs_node *dir, const char *name, const char *path)
2251 {
2252 	nfs_fhandle fhandle;
2253 	struct stat st;
2254 	struct XDROutPacket call;
2255 	struct XDRInPacket reply;
2256 	status_t result;
2257 	uint8 *replyBuf;
2258 	int32 status;
2259 	fs_node *newNode;
2260 
2261 	XDROutPacketInit (&call);
2262 	XDRInPacketInit (&reply);
2263 
2264 	result=nfs_lookup(ns,&dir->fhandle,name,&fhandle,&st);
2265 
2266 	if (result==B_OK)
2267 	{
2268 		void *dummy;
2269 		if ((result=get_vnode(ns->nsid,st.st_ino,&dummy))<B_OK)
2270 			return result;
2271 
2272 		XDRInPacketDestroy (&reply);
2273 		XDROutPacketDestroy (&call);
2274 		return EEXIST;
2275 	}
2276 	else if (result!=ENOENT)
2277 	{
2278 		XDRInPacketDestroy (&reply);
2279 		XDROutPacketDestroy (&call);
2280 		return result;
2281 	}
2282 
2283 	XDROutPacketAddFixed (&call,dir->fhandle.opaque,NFS_FHSIZE);
2284 	XDROutPacketAddString(&call,name);
2285 	XDROutPacketAddString(&call,path);
2286 	XDROutPacketAddInt32 (&call,S_IFLNK);
2287 	XDROutPacketAddInt32 (&call,-1);
2288 	XDROutPacketAddInt32 (&call,-1);
2289 	XDROutPacketAddInt32 (&call,-1);
2290 	XDROutPacketAddInt32 (&call,time(NULL));
2291 	XDROutPacketAddInt32 (&call,0);
2292 	XDROutPacketAddInt32 (&call,time(NULL));
2293 	XDROutPacketAddInt32 (&call,0);
2294 
2295 	replyBuf=send_rpc_call (ns,&ns->nfsAddr,NFS_PROGRAM,NFS_VERSION,NFSPROC_SYMLINK,&call);
2296 
2297 	if (!replyBuf)
2298 	{
2299 		XDRInPacketDestroy (&reply);
2300 		XDROutPacketDestroy (&call);
2301 		return B_ERROR;
2302 	}
2303 
2304 	XDRInPacketSetTo (&reply,replyBuf,0);
2305 
2306 	if (!is_successful_reply(&reply))
2307 	{
2308 		XDRInPacketDestroy (&reply);
2309 		XDROutPacketDestroy (&call);
2310 		return B_ERROR;
2311 	}
2312 
2313 	status=XDRInPacketGetInt32(&reply);
2314 
2315 /*	if (status!=NFS_OK)
2316 		return map_nfs_to_system_error(status);
2317 
2318 	ignore status here, weird thing, nfsservers that is
2319 */
2320 
2321 	result=nfs_lookup(ns,&dir->fhandle,name,&fhandle,&st);
2322 
2323 	if (result<B_OK)
2324 	{
2325 		XDRInPacketDestroy (&reply);
2326 		XDROutPacketDestroy (&call);
2327 		return result;
2328 	}
2329 
2330 	newNode=(fs_node *)malloc(sizeof(fs_node));
2331 	newNode->fhandle=fhandle;
2332 	newNode->vnid=st.st_ino;
2333 
2334 	insert_node (ns,newNode);
2335 
2336 	result=my_notify_listener (B_ENTRY_CREATED,ns->nsid,dir->vnid,0,st.st_ino,name);
2337 
2338 	XDRInPacketDestroy (&reply);
2339 	XDROutPacketDestroy (&call);
2340 	return result;
2341 }
2342 
2343 int	fs_access(void *ns, void *node, int mode)
2344 {
2345 	return B_OK;
2346 }
2347 
2348