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
RequestBuilder(Procedure proc)23 RequestBuilder::RequestBuilder(Procedure proc)
24 :
25 fOpCount(0),
26 fProcedure(proc),
27 fRequest(NULL)
28 {
29 _InitHeader();
30 }
31
32
~RequestBuilder()33 RequestBuilder::~RequestBuilder()
34 {
35 delete fRequest;
36 }
37
38
39 void
_InitHeader()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
Access()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
Close(uint32 seq,const uint32 * id,uint32 stateSeq)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
Commit(uint64 offset,uint32 count)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
Create(FileType type,const char * name,AttrValue * attr,uint32 count,const char * path)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
DelegReturn(const uint32 * id,uint32 seq)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
GetAttr(Attribute * attrs,uint32 count)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
GetFH()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
_GenerateLockOwner(XDR::WriteStream & stream,OpenState * state,LockOwner * owner)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
Lock(OpenState * state,LockInfo * lock,uint32 * sequence,bool reclaim)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
LockT(LockType type,uint64 pos,uint64 len,OpenState * state)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
LockU(LockInfo * lock)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
Link(const char * name)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
LookUp(const char * name)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
LookUpUp()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
Nverify(AttrValue * attr,uint32 count)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
Open(OpenClaim claim,uint32 seq,uint32 access,uint64 id,OpenCreate oc,uint64 ownerId,const char * name,AttrValue * attr,uint32 count,bool excl,OpenDelegation delegationType)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
OpenConfirm(uint32 seq,const uint32 * id,uint32 stateSeq)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
OpenAttrDir(bool create)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
PutFH(const FileHandle & fh)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
PutRootFH()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
Read(const uint32 * id,uint32 stateSeq,uint64 pos,uint32 len)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
ReadDir(uint64 cookie,uint64 cookieVerf,Attribute * attrs,uint32 attrCount)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
ReadLink()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
Remove(const char * file)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
Rename(const char * from,const char * to)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
Renew(uint64 clientId)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
SaveFH()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
SetAttr(const uint32 * id,uint32 stateSeq,AttrValue * attr,uint32 count)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
SetClientID(RPC::Server * server)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
_GenerateClientId(XDR::WriteStream & stream,const RPC::Server * server)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
SetClientIDConfirm(uint64 id,uint64 ver)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
Verify(AttrValue * attr,uint32 count)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
Write(const uint32 * id,uint32 stateSeq,const void * buffer,uint64 pos,uint32 len,bool stable)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
ReleaseLockOwner(OpenState * state,LockOwner * owner)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*
Request()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
_AttrBitmap(XDR::WriteStream & stream,Attribute * attrs,uint32 count)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
_EncodeAttrs(XDR::WriteStream & stream,AttrValue * attr,uint32 count)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