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