1 /* 2 * Copyright 2012 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Paweł Dziepak, pdziepak@quarnos.org 7 */ 8 9 10 #include "RequestBuilder.h" 11 12 #include <errno.h> 13 #include <string.h> 14 15 #include <util/Random.h> 16 17 #include "Cookie.h" 18 #include "OpenState.h" 19 #include "RPCCallback.h" 20 #include "RPCCallbackServer.h" 21 22 23 RequestBuilder::RequestBuilder(Procedure proc) 24 : 25 fOpCount(0), 26 fProcedure(proc), 27 fRequest(NULL) 28 { 29 _InitHeader(); 30 } 31 32 33 RequestBuilder::~RequestBuilder() 34 { 35 delete fRequest; 36 } 37 38 39 void 40 RequestBuilder::_InitHeader() 41 { 42 fRequest = RPC::Call::Create(fProcedure, RPC::Auth::CreateSys(), 43 RPC::Auth::CreateNone()); 44 45 if (fRequest == NULL) 46 return; 47 48 if (fProcedure == ProcCompound) { 49 fRequest->Stream().AddOpaque(NULL, 0); 50 fRequest->Stream().AddUInt(0); 51 52 fOpCountPosition = fRequest->Stream().Current(); 53 fRequest->Stream().AddUInt(0); 54 } 55 } 56 57 58 status_t 59 RequestBuilder::Access() 60 { 61 if (fProcedure != ProcCompound) 62 return B_BAD_VALUE; 63 if (fRequest == NULL) 64 return B_NO_MEMORY; 65 66 fRequest->Stream().AddUInt(OpAccess); 67 fRequest->Stream().AddUInt(ACCESS4_READ | ACCESS4_LOOKUP | ACCESS4_MODIFY 68 | ACCESS4_EXTEND | ACCESS4_DELETE | ACCESS4_EXECUTE); 69 fOpCount++; 70 71 return B_OK; 72 } 73 74 75 status_t 76 RequestBuilder::Close(uint32 seq, const uint32* id, uint32 stateSeq) 77 { 78 if (fProcedure != ProcCompound) 79 return B_BAD_VALUE; 80 if (fRequest == NULL) 81 return B_NO_MEMORY; 82 83 fRequest->Stream().AddUInt(OpClose); 84 fRequest->Stream().AddUInt(seq); 85 fRequest->Stream().AddUInt(stateSeq); 86 fRequest->Stream().AddUInt(id[0]); 87 fRequest->Stream().AddUInt(id[1]); 88 fRequest->Stream().AddUInt(id[2]); 89 90 fOpCount++; 91 92 return B_OK; 93 } 94 95 96 status_t 97 RequestBuilder::Commit(uint64 offset, uint32 count) 98 { 99 if (fProcedure != ProcCompound) 100 return B_BAD_VALUE; 101 if (fRequest == NULL) 102 return B_NO_MEMORY; 103 104 fRequest->Stream().AddUInt(OpCommit); 105 fRequest->Stream().AddUHyper(offset); 106 fRequest->Stream().AddUInt(count); 107 108 fOpCount++; 109 110 return B_OK; 111 } 112 113 114 status_t 115 RequestBuilder::Create(FileType type, const char* name, AttrValue* attr, 116 uint32 count, const char* path) 117 { 118 if (fProcedure != ProcCompound) 119 return B_BAD_VALUE; 120 if (fRequest == NULL) 121 return B_NO_MEMORY; 122 if (type == NF4LNK && path == NULL) 123 return B_BAD_VALUE; 124 if (name == NULL) 125 return B_BAD_VALUE; 126 if (type == NF4BLK || type == NF4CHR) 127 return B_BAD_VALUE; 128 129 fRequest->Stream().AddUInt(OpCreate); 130 fRequest->Stream().AddUInt(type); 131 if (type == NF4LNK) 132 fRequest->Stream().AddString(path); 133 fRequest->Stream().AddString(name); 134 _EncodeAttrs(fRequest->Stream(), attr, count); 135 136 fOpCount++; 137 138 return B_OK; 139 } 140 141 142 status_t 143 RequestBuilder::DelegReturn(const uint32* id, uint32 seq) 144 { 145 if (fProcedure != ProcCompound) 146 return B_BAD_VALUE; 147 if (fRequest == NULL) 148 return B_NO_MEMORY; 149 150 fRequest->Stream().AddUInt(OpDelegReturn); 151 152 fRequest->Stream().AddUInt(seq); 153 fRequest->Stream().AddUInt(id[0]); 154 fRequest->Stream().AddUInt(id[1]); 155 fRequest->Stream().AddUInt(id[2]); 156 157 fOpCount++; 158 159 return B_OK; 160 } 161 162 163 status_t 164 RequestBuilder::GetAttr(Attribute* attrs, uint32 count) 165 { 166 if (fProcedure != ProcCompound) 167 return B_BAD_VALUE; 168 if (fRequest == NULL) 169 return B_NO_MEMORY; 170 171 fRequest->Stream().AddUInt(OpGetAttr); 172 _AttrBitmap(fRequest->Stream(), attrs, count); 173 174 fOpCount++; 175 176 return B_OK; 177 } 178 179 180 status_t 181 RequestBuilder::GetFH() 182 { 183 if (fProcedure != ProcCompound) 184 return B_BAD_VALUE; 185 if (fRequest == NULL) 186 return B_NO_MEMORY; 187 188 fRequest->Stream().AddUInt(OpGetFH); 189 fOpCount++; 190 191 return B_OK; 192 } 193 194 195 void 196 RequestBuilder::_GenerateLockOwner(XDR::WriteStream& stream, 197 OpenState* state, LockOwner* owner) 198 { 199 stream.AddUHyper(state->fClientID); 200 201 uint64 lockOwner[2]; 202 lockOwner[0] = owner->fOwner; 203 lockOwner[1] = state->fInfo.fFileId; 204 stream.AddOpaque(lockOwner, sizeof(lockOwner)); 205 } 206 207 208 status_t 209 RequestBuilder::Lock(OpenState* state, LockInfo* lock, uint32* sequence, 210 bool reclaim) 211 { 212 if (fProcedure != ProcCompound) 213 return B_BAD_VALUE; 214 if (fRequest == NULL) 215 return B_NO_MEMORY; 216 217 fRequest->Stream().AddUInt(OpLock); 218 219 fRequest->Stream().AddInt(lock->fType); 220 fRequest->Stream().AddBoolean(reclaim); 221 222 fRequest->Stream().AddUHyper(lock->fStart); 223 fRequest->Stream().AddUHyper(lock->fLength); 224 225 if (lock->fOwner->fStateId[0] == 0 && lock->fOwner->fStateId[1] == 0 226 && lock->fOwner->fStateId[2] == 0) { 227 228 fRequest->Stream().AddBoolean(true); // new lock owner 229 230 // open seq stateid 231 fRequest->Stream().AddUInt(*sequence); 232 fRequest->Stream().AddUInt(state->fStateSeq); 233 fRequest->Stream().AddUInt(state->fStateID[0]); 234 fRequest->Stream().AddUInt(state->fStateID[1]); 235 fRequest->Stream().AddUInt(state->fStateID[2]); 236 237 // lock seq owner 238 fRequest->Stream().AddUInt(lock->fOwner->fSequence++); 239 _GenerateLockOwner(fRequest->Stream(), state, lock->fOwner); 240 241 } else { 242 fRequest->Stream().AddBoolean(false); // old lock owner 243 (*sequence)--; 244 245 // lock stateid seq 246 fRequest->Stream().AddUInt(lock->fOwner->fStateSeq); 247 fRequest->Stream().AddUInt(lock->fOwner->fStateId[0]); 248 fRequest->Stream().AddUInt(lock->fOwner->fStateId[1]); 249 fRequest->Stream().AddUInt(lock->fOwner->fStateId[2]); 250 251 fRequest->Stream().AddUInt(lock->fOwner->fSequence++); 252 } 253 254 fOpCount++; 255 256 return B_OK; 257 } 258 259 260 status_t 261 RequestBuilder::LockT(LockType type, uint64 pos, uint64 len, 262 OpenState* state) 263 { 264 if (fProcedure != ProcCompound) 265 return B_BAD_VALUE; 266 if (fRequest == NULL) 267 return B_NO_MEMORY; 268 269 fRequest->Stream().AddUInt(OpLockT); 270 271 fRequest->Stream().AddInt(type); 272 273 fRequest->Stream().AddUHyper(pos); 274 fRequest->Stream().AddUHyper(len); 275 276 fRequest->Stream().AddUHyper(state->fClientID); 277 278 uint32 owner = find_thread(NULL); 279 fRequest->Stream().AddOpaque(&owner, sizeof(owner)); 280 281 fOpCount++; 282 283 return B_OK; 284 } 285 286 287 status_t 288 RequestBuilder::LockU(LockInfo* lock) 289 { 290 if (fProcedure != ProcCompound) 291 return B_BAD_VALUE; 292 if (fRequest == NULL) 293 return B_NO_MEMORY; 294 295 fRequest->Stream().AddUInt(OpLockU); 296 297 fRequest->Stream().AddInt(lock->fType); 298 299 fRequest->Stream().AddUInt(lock->fOwner->fSequence++); 300 fRequest->Stream().AddUInt(lock->fOwner->fStateSeq); 301 fRequest->Stream().AddUInt(lock->fOwner->fStateId[0]); 302 fRequest->Stream().AddUInt(lock->fOwner->fStateId[1]); 303 fRequest->Stream().AddUInt(lock->fOwner->fStateId[2]); 304 305 fRequest->Stream().AddUHyper(lock->fStart); 306 fRequest->Stream().AddUHyper(lock->fLength); 307 308 fOpCount++; 309 310 return B_OK; 311 } 312 313 314 status_t 315 RequestBuilder::Link(const char* name) 316 { 317 if (fProcedure != ProcCompound) 318 return B_BAD_VALUE; 319 if (fRequest == NULL) 320 return B_NO_MEMORY; 321 if (name == NULL) 322 return B_BAD_VALUE; 323 324 fRequest->Stream().AddUInt(OpLink); 325 fRequest->Stream().AddString(name); 326 fOpCount++; 327 328 return B_OK; 329 } 330 331 332 status_t 333 RequestBuilder::LookUp(const char* name) 334 { 335 if (fProcedure != ProcCompound) 336 return B_BAD_VALUE; 337 if (fRequest == NULL) 338 return B_NO_MEMORY; 339 if (name == NULL) 340 return B_BAD_VALUE; 341 342 fRequest->Stream().AddUInt(OpLookUp); 343 fRequest->Stream().AddString(name, strlen(name)); 344 fOpCount++; 345 346 return B_OK; 347 } 348 349 350 status_t 351 RequestBuilder::LookUpUp() 352 { 353 if (fProcedure != ProcCompound) 354 return B_BAD_VALUE; 355 if (fRequest == NULL) 356 return B_NO_MEMORY; 357 358 fRequest->Stream().AddUInt(OpLookUpUp); 359 fOpCount++; 360 361 return B_OK; 362 } 363 364 365 status_t 366 RequestBuilder::Nverify(AttrValue* attr, uint32 count) 367 { 368 if (fProcedure != ProcCompound) 369 return B_BAD_VALUE; 370 if (fRequest == NULL) 371 return B_NO_MEMORY; 372 373 fRequest->Stream().AddUInt(OpNverify); 374 _EncodeAttrs(fRequest->Stream(), attr, count); 375 376 fOpCount++; 377 378 return B_OK; 379 } 380 381 382 status_t 383 RequestBuilder::Open(OpenClaim claim, uint32 seq, uint32 access, uint64 id, 384 OpenCreate oc, uint64 ownerId, const char* name, AttrValue* attr, 385 uint32 count, bool excl, OpenDelegation delegationType) 386 { 387 if (fProcedure != ProcCompound) 388 return B_BAD_VALUE; 389 if (fRequest == NULL) 390 return B_NO_MEMORY; 391 392 fRequest->Stream().AddUInt(OpOpen); 393 fRequest->Stream().AddUInt(seq); 394 fRequest->Stream().AddUInt(access); 395 fRequest->Stream().AddUInt(0); // deny none 396 fRequest->Stream().AddUHyper(id); 397 398 char owner[128]; 399 int pos = 0; 400 *(uint64*)(owner + pos) = ownerId; 401 pos += sizeof(uint64); 402 403 fRequest->Stream().AddOpaque(owner, pos); 404 405 fRequest->Stream().AddUInt(oc); 406 if (oc == OPEN4_CREATE) { 407 fRequest->Stream().AddInt(excl ? GUARDED4 : UNCHECKED4); 408 _EncodeAttrs(fRequest->Stream(), attr, count); 409 } 410 411 fRequest->Stream().AddUInt(claim); 412 switch (claim) { 413 case CLAIM_NULL: 414 fRequest->Stream().AddString(name, strlen(name)); 415 break; 416 case CLAIM_PREVIOUS: 417 fRequest->Stream().AddUInt(delegationType); 418 break; 419 default: 420 return B_UNSUPPORTED; 421 } 422 423 fOpCount++; 424 425 return B_OK; 426 } 427 428 429 status_t 430 RequestBuilder::OpenConfirm(uint32 seq, const uint32* id, uint32 stateSeq) 431 { 432 if (fProcedure != ProcCompound) 433 return B_BAD_VALUE; 434 if (fRequest == NULL) 435 return B_NO_MEMORY; 436 437 fRequest->Stream().AddUInt(OpOpenConfirm); 438 fRequest->Stream().AddUInt(stateSeq); 439 fRequest->Stream().AddUInt(id[0]); 440 fRequest->Stream().AddUInt(id[1]); 441 fRequest->Stream().AddUInt(id[2]); 442 fRequest->Stream().AddUInt(seq); 443 444 fOpCount++; 445 446 return B_OK; 447 } 448 449 450 status_t 451 RequestBuilder::OpenAttrDir(bool create) 452 { 453 if (fProcedure != ProcCompound) 454 return B_BAD_VALUE; 455 if (fRequest == NULL) 456 return B_NO_MEMORY; 457 458 fRequest->Stream().AddUInt(OpOpenAttrDir); 459 fRequest->Stream().AddBoolean(create); 460 461 fOpCount++; 462 463 return B_OK; 464 } 465 466 467 status_t 468 RequestBuilder::PutFH(const FileHandle& fh) 469 { 470 if (fProcedure != ProcCompound) 471 return B_BAD_VALUE; 472 if (fRequest == NULL) 473 return B_NO_MEMORY; 474 475 fRequest->Stream().AddUInt(OpPutFH); 476 fRequest->Stream().AddOpaque(fh.fData, fh.fSize); 477 fOpCount++; 478 479 return B_OK; 480 } 481 482 483 status_t 484 RequestBuilder::PutRootFH() 485 { 486 if (fProcedure != ProcCompound) 487 return B_BAD_VALUE; 488 if (fRequest == NULL) 489 return B_NO_MEMORY; 490 491 fRequest->Stream().AddUInt(OpPutRootFH); 492 fOpCount++; 493 494 return B_OK; 495 } 496 497 498 status_t 499 RequestBuilder::Read(const uint32* id, uint32 stateSeq, uint64 pos, uint32 len) 500 { 501 if (fProcedure != ProcCompound) 502 return B_BAD_VALUE; 503 if (fRequest == NULL) 504 return B_NO_MEMORY; 505 506 fRequest->Stream().AddUInt(OpRead); 507 fRequest->Stream().AddUInt(stateSeq); 508 fRequest->Stream().AddUInt(id[0]); 509 fRequest->Stream().AddUInt(id[1]); 510 fRequest->Stream().AddUInt(id[2]); 511 fRequest->Stream().AddUHyper(pos); 512 fRequest->Stream().AddUInt(len); 513 514 fOpCount++; 515 516 return B_OK; 517 } 518 519 520 status_t 521 RequestBuilder::ReadDir(uint64 cookie, uint64 cookieVerf, Attribute* attrs, 522 uint32 attrCount) 523 { 524 if (fProcedure != ProcCompound) 525 return B_BAD_VALUE; 526 if (fRequest == NULL) 527 return B_NO_MEMORY; 528 529 fRequest->Stream().AddUInt(OpReadDir); 530 fRequest->Stream().AddUHyper(cookie); 531 fRequest->Stream().AddUHyper(cookieVerf); 532 533 // consider predicting this values basing on count or buffer size 534 fRequest->Stream().AddUInt(0x2000); 535 fRequest->Stream().AddUInt(0x8000); 536 _AttrBitmap(fRequest->Stream(), attrs, attrCount); 537 538 fOpCount++; 539 540 return B_OK; 541 } 542 543 544 status_t 545 RequestBuilder::ReadLink() 546 { 547 if (fProcedure != ProcCompound) 548 return B_BAD_VALUE; 549 if (fRequest == NULL) 550 return B_NO_MEMORY; 551 552 fRequest->Stream().AddUInt(OpReadLink); 553 554 fOpCount++; 555 556 return B_OK; 557 } 558 559 560 status_t 561 RequestBuilder::Remove(const char* file) 562 { 563 if (fProcedure != ProcCompound) 564 return B_BAD_VALUE; 565 if (fRequest == NULL) 566 return B_NO_MEMORY; 567 568 fRequest->Stream().AddUInt(OpRemove); 569 fRequest->Stream().AddString(file); 570 571 fOpCount++; 572 573 return B_OK; 574 } 575 576 577 status_t 578 RequestBuilder::Rename(const char* from, const char* to) 579 { 580 if (fProcedure != ProcCompound) 581 return B_BAD_VALUE; 582 if (fRequest == NULL) 583 return B_NO_MEMORY; 584 585 fRequest->Stream().AddUInt(OpRename); 586 fRequest->Stream().AddString(from); 587 fRequest->Stream().AddString(to); 588 589 fOpCount++; 590 591 return B_OK; 592 } 593 594 595 status_t 596 RequestBuilder::Renew(uint64 clientId) 597 { 598 if (fProcedure != ProcCompound) 599 return B_BAD_VALUE; 600 if (fRequest == NULL) 601 return B_NO_MEMORY; 602 603 fRequest->Stream().AddUInt(OpRenew); 604 fRequest->Stream().AddUHyper(clientId); 605 606 fOpCount++; 607 608 return B_OK; 609 } 610 611 612 status_t 613 RequestBuilder::SaveFH() 614 { 615 if (fProcedure != ProcCompound) 616 return B_BAD_VALUE; 617 if (fRequest == NULL) 618 return B_NO_MEMORY; 619 620 fRequest->Stream().AddUInt(OpSaveFH); 621 fOpCount++; 622 623 return B_OK; 624 } 625 626 627 status_t 628 RequestBuilder::SetAttr(const uint32* id, uint32 stateSeq, AttrValue* attr, 629 uint32 count) 630 { 631 if (fProcedure != ProcCompound) 632 return B_BAD_VALUE; 633 if (fRequest == NULL) 634 return B_NO_MEMORY; 635 636 fRequest->Stream().AddUInt(OpSetAttr); 637 fRequest->Stream().AddUInt(stateSeq); 638 if (id != NULL) { 639 fRequest->Stream().AddUInt(id[0]); 640 fRequest->Stream().AddUInt(id[1]); 641 fRequest->Stream().AddUInt(id[2]); 642 } else { 643 fRequest->Stream().AddUInt(0); 644 fRequest->Stream().AddUInt(0); 645 fRequest->Stream().AddUInt(0); 646 } 647 _EncodeAttrs(fRequest->Stream(), attr, count); 648 649 fOpCount++; 650 651 return B_OK; 652 } 653 654 655 status_t 656 RequestBuilder::SetClientID(RPC::Server* server) 657 { 658 if (fProcedure != ProcCompound) 659 return B_BAD_VALUE; 660 if (fRequest == NULL) 661 return B_NO_MEMORY; 662 663 fRequest->Stream().AddUInt(OpSetClientID); 664 uint64 verifier = get_random<uint64>(); 665 fRequest->Stream().AddUHyper(verifier); 666 667 status_t result = _GenerateClientId(fRequest->Stream(), server); 668 if (result != B_OK) 669 return result; 670 671 fRequest->Stream().AddUInt(0x40000000); 672 673 if (server->GetCallback() != NULL) { 674 ASSERT(server->GetCallback()->CBServer() != NULL); 675 676 uint32 id = server->GetCallback()->ID(); 677 678 PeerAddress local = server->GetCallback()->CBServer()->LocalID(); 679 PeerAddress servAddr = server->LocalID(); 680 servAddr.SetPort(local.Port()); 681 682 fRequest->Stream().AddString(local.ProtocolString()); 683 684 char* uAddr = servAddr.UniversalAddress(); 685 if (uAddr == NULL) 686 return B_NO_MEMORY; 687 fRequest->Stream().AddString(uAddr); 688 free(uAddr); 689 690 fRequest->Stream().AddUInt(id); 691 } else { 692 fRequest->Stream().AddString(""); 693 fRequest->Stream().AddString(""); 694 fRequest->Stream().AddUInt(0); 695 } 696 697 fOpCount++; 698 699 return B_OK; 700 } 701 702 703 status_t 704 RequestBuilder::_GenerateClientId(XDR::WriteStream& stream, 705 const RPC::Server* server) 706 { 707 char id[512] = "HAIKU:kernel:"; 708 int pos = strlen(id); 709 710 PeerAddress local = server->LocalID(); 711 712 memcpy(id + pos, server->ID().InAddr(), server->ID().InAddrSize()); 713 pos += server->ID().InAddrSize(); 714 715 memcpy(id + pos, local.InAddr(), local.InAddrSize()); 716 pos += local.InAddrSize(); 717 718 *(uint16*)(id + pos) = server->ID().Port(); 719 pos += sizeof(uint16); 720 721 *(uint16*)(id + pos) = server->ID().fProtocol; 722 pos += sizeof(uint16); 723 724 stream.AddOpaque(id, pos); 725 726 return B_OK; 727 } 728 729 730 status_t 731 RequestBuilder::SetClientIDConfirm(uint64 id, uint64 ver) 732 { 733 if (fProcedure != ProcCompound) 734 return B_BAD_VALUE; 735 if (fRequest == NULL) 736 return B_NO_MEMORY; 737 738 fRequest->Stream().AddUInt(OpSetClientIDConfirm); 739 fRequest->Stream().AddUHyper(id); 740 fRequest->Stream().AddUHyper(ver); 741 742 fOpCount++; 743 744 return B_OK; 745 } 746 747 748 status_t 749 RequestBuilder::Verify(AttrValue* attr, uint32 count) 750 { 751 if (fProcedure != ProcCompound) 752 return B_BAD_VALUE; 753 if (fRequest == NULL) 754 return B_NO_MEMORY; 755 756 fRequest->Stream().AddUInt(OpVerify); 757 _EncodeAttrs(fRequest->Stream(), attr, count); 758 759 fOpCount++; 760 761 return B_OK; 762 } 763 764 765 status_t 766 RequestBuilder::Write(const uint32* id, uint32 stateSeq, const void* buffer, 767 uint64 pos, uint32 len, bool stable) 768 { 769 if (fProcedure != ProcCompound) 770 return B_BAD_VALUE; 771 if (fRequest == NULL) 772 return B_NO_MEMORY; 773 774 fRequest->Stream().AddUInt(OpWrite); 775 fRequest->Stream().AddUInt(stateSeq); 776 fRequest->Stream().AddUInt(id[0]); 777 fRequest->Stream().AddUInt(id[1]); 778 fRequest->Stream().AddUInt(id[2]); 779 fRequest->Stream().AddUHyper(pos); 780 fRequest->Stream().AddInt(stable ? FILE_SYNC4 : UNSTABLE4); 781 fRequest->Stream().AddOpaque(buffer, len); 782 783 fOpCount++; 784 785 return B_OK; 786 } 787 788 789 status_t 790 RequestBuilder::ReleaseLockOwner(OpenState* state, LockOwner* owner) 791 { 792 if (fProcedure != ProcCompound) 793 return B_BAD_VALUE; 794 if (fRequest == NULL) 795 return B_NO_MEMORY; 796 797 fRequest->Stream().AddUInt(OpReleaseLockOwner); 798 _GenerateLockOwner(fRequest->Stream(), state, owner); 799 800 fOpCount++; 801 802 return B_OK; 803 } 804 805 806 RPC::Call* 807 RequestBuilder::Request() 808 { 809 if (fRequest == NULL) 810 return NULL; 811 812 if (fProcedure == ProcCompound) 813 fRequest->Stream().InsertUInt(fOpCountPosition, fOpCount); 814 815 if (fRequest->Stream().Error() == B_OK) 816 return fRequest; 817 else 818 return NULL; 819 } 820 821 822 void 823 RequestBuilder::_AttrBitmap(XDR::WriteStream& stream, Attribute* attrs, 824 uint32 count) 825 { 826 // 2 is safe in NFS4, not in NFS4.1 though 827 uint32 bitmap[2]; 828 memset(bitmap, 0, sizeof(bitmap)); 829 for (uint32 i = 0; i < count; i++) { 830 bitmap[attrs[i] / 32] |= 1 << attrs[i] % 32; 831 } 832 833 uint32 bcount = bitmap[1] != 0 ? 2 : 1; 834 stream.AddUInt(bcount); 835 for (uint32 i = 0; i < bcount; i++) 836 stream.AddUInt(bitmap[i]); 837 } 838 839 840 void 841 RequestBuilder::_EncodeAttrs(XDR::WriteStream& stream, AttrValue* attr, 842 uint32 count) 843 { 844 if (count == 0) { 845 stream.AddUInt(0); 846 stream.AddOpaque(NULL, 0); 847 return; 848 } 849 850 Attribute* attrs 851 = reinterpret_cast<Attribute*>(malloc(sizeof(Attribute) * count)); 852 for (uint32 i = 0; i < count; i++) 853 attrs[i] = static_cast<Attribute>(attr[i].fAttribute); 854 _AttrBitmap(stream, attrs, count); 855 free(attrs); 856 857 uint32 i = 0; 858 XDR::WriteStream str; 859 if (i < count && attr[i].fAttribute == FATTR4_TYPE) { 860 str.AddUInt(attr[i].fData.fValue32); 861 i++; 862 } 863 864 if (i < count && attr[i].fAttribute == FATTR4_SIZE) { 865 str.AddUHyper(attr[i].fData.fValue64); 866 i++; 867 } 868 869 if (i < count && attr[i].fAttribute == FATTR4_FILEHANDLE) { 870 FileHandle* fh = reinterpret_cast<FileHandle*>(attr[i].fData.fPointer); 871 str.AddOpaque(fh->fData, fh->fSize); 872 i++; 873 } 874 875 if (i < count && attr[i].fAttribute == FATTR4_FILEID) { 876 str.AddUHyper(attr[i].fData.fValue64); 877 i++; 878 } 879 880 if (i < count && attr[i].fAttribute == FATTR4_MODE) { 881 str.AddUInt(attr[i].fData.fValue32); 882 i++; 883 } 884 885 if (i < count && attr[i].fAttribute == FATTR4_OWNER) { 886 str.AddString(reinterpret_cast<char*>(attr[i].fData.fPointer)); 887 i++; 888 } 889 890 if (i < count && attr[i].fAttribute == FATTR4_OWNER_GROUP) { 891 str.AddString(reinterpret_cast<char*>(attr[i].fData.fPointer)); 892 i++; 893 } 894 895 if (i < count && attr[i].fAttribute == FATTR4_TIME_ACCESS_SET) { 896 str.AddInt(1); // SET_TO_CLIENT_TIME4 897 898 struct timespec* ts 899 = reinterpret_cast<timespec*>(attr[i].fData.fPointer); 900 str.AddHyper(ts->tv_sec); 901 str.AddUInt(ts->tv_nsec); 902 903 i++; 904 } 905 906 if (i < count && attr[i].fAttribute == FATTR4_TIME_MODIFY_SET) { 907 str.AddInt(1); // SET_TO_CLIENT_TIME4 908 909 struct timespec* ts 910 = reinterpret_cast<timespec*>(attr[i].fData.fPointer); 911 str.AddHyper(ts->tv_sec); 912 str.AddUInt(ts->tv_nsec); 913 914 i++; 915 } 916 917 stream.AddOpaque(str); 918 } 919 920