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