xref: /haiku/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp (revision 0c481598be65652e10dda95cb1a8dfb624d23879)
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