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