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