BPicture: Fix archive constructor.
[haiku.git] / src / add-ons / kernel / file_systems / nfs4 / ReplyInterpreter.cpp
bloba965b9e8cd79348c2bd635f80b085668e518e5a3
1 /*
2 * Copyright 2012 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Paweł Dziepak, pdziepak@quarnos.org
7 */
10 #include "ReplyInterpreter.h"
12 #include <string.h>
14 #include <AutoDeleter.h>
15 #include <util/kernel_cpp.h>
17 #include "Cookie.h"
20 FSLocation::~FSLocation()
22 if (fRootPath != NULL) {
23 for (uint32 i = 0; fRootPath[i] != NULL; i++)
24 free(const_cast<char*>(fRootPath[i]));
26 delete[] fRootPath;
28 for (uint32 i = 0; i < fCount; i++)
29 free(const_cast<char*>(fLocations[i]));
30 delete[] fLocations;
34 FSLocations::~FSLocations()
36 if (fRootPath != NULL) {
37 for (uint32 i = 0; fRootPath[i] != NULL; i++)
38 free(const_cast<char*>(fRootPath[i]));
40 delete[] fRootPath;
42 delete[] fLocations;
46 AttrValue::AttrValue()
48 fAttribute(0),
49 fFreePointer(false)
54 AttrValue::~AttrValue()
56 if (fFreePointer)
57 free(fData.fPointer);
58 if (fAttribute == FATTR4_FS_LOCATIONS)
59 delete fData.fLocations;
63 DirEntry::DirEntry()
65 fName(NULL),
66 fAttrs(NULL),
67 fAttrCount(0)
72 DirEntry::~DirEntry()
74 free(const_cast<char*>(fName));
75 delete[] fAttrs;
79 ReplyInterpreter::ReplyInterpreter(RPC::Reply* reply)
81 fNFS4Error(NFS4_OK),
82 fDecodeError(false),
83 fReply(reply)
85 if (reply != NULL)
86 _ParseHeader();
90 ReplyInterpreter::~ReplyInterpreter()
92 delete fReply;
96 void
97 ReplyInterpreter::_ParseHeader()
99 fNFS4Error = fReply->Stream().GetUInt();
100 fReply->Stream().GetOpaque(NULL);
101 fReply->Stream().GetUInt();
105 status_t
106 ReplyInterpreter::Access(uint32* supported, uint32* allowed)
108 status_t res = _OperationError(OpAccess);
109 if (res != B_OK)
110 return res;
112 uint32 support = fReply->Stream().GetUInt();
113 uint32 allow = fReply->Stream().GetUInt();
115 if (supported != NULL)
116 *supported = support;
117 if (allowed != NULL)
118 *allowed = allow;
120 return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
124 status_t
125 ReplyInterpreter::Close()
127 status_t res = _OperationError(OpClose);
128 if (res != B_OK)
129 return res;
131 fReply->Stream().GetUInt();
132 fReply->Stream().GetUInt();
133 fReply->Stream().GetUInt();
134 fReply->Stream().GetUInt();
136 return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
140 status_t
141 ReplyInterpreter::Commit()
143 status_t res = _OperationError(OpCommit);
144 if (res != B_OK)
145 return res;
147 fReply->Stream().GetOpaque(NULL);
149 return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
153 status_t
154 ReplyInterpreter::Create(uint64* before, uint64* after, bool& atomic)
156 status_t res = _OperationError(OpCreate);
157 if (res != B_OK)
158 return res;
160 atomic = fReply->Stream().GetBoolean();
161 *before = fReply->Stream().GetUHyper();
162 *after = fReply->Stream().GetUHyper();
164 uint32 count = fReply->Stream().GetUInt();
165 for (uint32 i = 0; i < count; i++)
166 fReply->Stream().GetUInt();
168 return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
172 // Bit Twiddling Hacks
173 // http://graphics.stanford.edu/~seander/bithacks.html
174 static inline uint32 CountBits(uint32 v)
176 v = v - ((v >> 1) & 0x55555555);
177 v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
178 return (((v + (v >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
182 status_t
183 ReplyInterpreter::GetAttr(AttrValue** attrs, uint32* count)
185 status_t res = _OperationError(OpGetAttr);
186 if (res != B_OK)
187 return res;
189 return _DecodeAttrs(fReply->Stream(), attrs, count);
193 status_t
194 ReplyInterpreter::GetFH(FileHandle* fh)
196 status_t res = _OperationError(OpGetFH);
197 if (res != B_OK)
198 return res;
200 uint32 size;
201 const void* ptr = fReply->Stream().GetOpaque(&size);
202 if (ptr == NULL || size > NFS4_FHSIZE)
203 return B_BAD_VALUE;
205 if (fh != NULL) {
206 fh->fSize = size;
207 memcpy(fh->fData, ptr, size);
210 return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
214 status_t
215 ReplyInterpreter::Link(uint64* before, uint64* after, bool& atomic)
217 status_t res = _OperationError(OpLink);
218 if (res != B_OK)
219 return res;
221 atomic = fReply->Stream().GetBoolean();
222 *before = fReply->Stream().GetUHyper();
223 *after = fReply->Stream().GetUHyper();
225 return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
229 status_t
230 ReplyInterpreter::Lock(LockInfo* linfo)
232 status_t res = _OperationError(OpLock);
233 if (res != B_OK)
234 return res;
236 linfo->fOwner->fStateSeq = fReply->Stream().GetUInt();
237 linfo->fOwner->fStateId[0] = fReply->Stream().GetUInt();
238 linfo->fOwner->fStateId[1] = fReply->Stream().GetUInt();
239 linfo->fOwner->fStateId[2] = fReply->Stream().GetUInt();
241 return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
245 status_t
246 ReplyInterpreter::LockT(uint64* pos, uint64* len, LockType* type)
248 status_t res = _OperationError(OpLockT);
249 if (res != B_WOULD_BLOCK || NFS4Error() != NFS4ERR_DENIED)
250 return res;
252 *pos = fReply->Stream().GetUHyper();
253 *len = fReply->Stream().GetUHyper();
254 *type = static_cast<LockType>(fReply->Stream().GetInt());
256 fReply->Stream().GetUHyper();
257 fReply->Stream().GetOpaque(NULL);
259 return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
263 status_t
264 ReplyInterpreter::LockU(LockInfo* linfo)
266 status_t res = _OperationError(OpLockU);
267 if (res != B_OK)
268 return res;
270 linfo->fOwner->fStateSeq = fReply->Stream().GetUInt();
271 linfo->fOwner->fStateId[0] = fReply->Stream().GetUInt();
272 linfo->fOwner->fStateId[1] = fReply->Stream().GetUInt();
273 linfo->fOwner->fStateId[2] = fReply->Stream().GetUInt();
275 return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
279 status_t
280 ReplyInterpreter::Open(uint32* id, uint32* seq, bool* confirm,
281 OpenDelegationData* delegData, ChangeInfo* changeInfo)
283 status_t res = _OperationError(OpOpen);
284 if (res != B_OK)
285 return res;
287 *seq = fReply->Stream().GetUInt();
288 id[0] = fReply->Stream().GetUInt();
289 id[1] = fReply->Stream().GetUInt();
290 id[2] = fReply->Stream().GetUInt();
292 // change info
293 bool atomic = fReply->Stream().GetBoolean();
294 uint64 before = fReply->Stream().GetUHyper();
295 uint64 after = fReply->Stream().GetUHyper();
296 if (changeInfo != NULL) {
297 changeInfo->fAtomic = atomic;
298 changeInfo->fBefore = before;
299 changeInfo->fAfter = after;
302 uint32 flags = fReply->Stream().GetUInt();
303 *confirm = (flags & OPEN4_RESULT_CONFIRM) == OPEN4_RESULT_CONFIRM;
305 // attrmask
306 uint32 bcount = fReply->Stream().GetUInt();
307 for (uint32 i = 0; i < bcount; i++)
308 fReply->Stream().GetUInt();
310 // delegation info
311 uint32 delegation = fReply->Stream().GetUInt();
312 OpenDelegationData data;
313 if (delegData == NULL)
314 delegData = &data;
316 if (delegation == OPEN_DELEGATE_NONE) {
317 delegData->fType = OPEN_DELEGATE_NONE;
318 return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
321 delegData->fStateSeq = fReply->Stream().GetUInt();
322 delegData->fStateID[0] = fReply->Stream().GetUInt();
323 delegData->fStateID[1] = fReply->Stream().GetUInt();
324 delegData->fStateID[2] = fReply->Stream().GetUInt();
326 delegData->fRecall = fReply->Stream().GetBoolean();
328 switch (delegation) {
329 case OPEN_DELEGATE_READ:
330 delegData->fType = OPEN_DELEGATE_READ;
331 break;
332 case OPEN_DELEGATE_WRITE:
333 delegData->fType = OPEN_DELEGATE_WRITE;
335 int32 limitBy = fReply->Stream().GetInt();
336 if (limitBy == NFS_LIMIT_SIZE)
337 delegData->fSpaceLimit = fReply->Stream().GetUHyper();
338 else if (limitBy == NFS_LIMIT_BLOCKS) {
339 uint32 numBlocks = fReply->Stream().GetUInt();
340 delegData->fSpaceLimit = fReply->Stream().GetUInt() * numBlocks;
342 break;
345 // ACE data
346 fReply->Stream().GetUInt();
347 fReply->Stream().GetUInt();
348 fReply->Stream().GetUInt();
349 fReply->Stream().GetOpaque(NULL);
351 return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
355 status_t
356 ReplyInterpreter::OpenConfirm(uint32* stateSeq)
358 status_t res = _OperationError(OpOpenConfirm);
359 if (res != B_OK)
360 return res;
362 *stateSeq = fReply->Stream().GetUInt();
363 fReply->Stream().GetUInt();
364 fReply->Stream().GetUInt();
365 fReply->Stream().GetUInt();
367 return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
371 status_t
372 ReplyInterpreter::Read(void* buffer, uint32* size, bool* eof)
374 status_t res = _OperationError(OpRead);
375 if (res != B_OK)
376 return res;
378 *eof = fReply->Stream().GetBoolean();
379 const void* ptr = fReply->Stream().GetOpaque(size);
380 memcpy(buffer, ptr, *size);
382 return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
386 status_t
387 ReplyInterpreter::ReadDir(uint64* cookie, uint64* cookieVerf,
388 DirEntry** dirents, uint32* _count, bool* eof)
390 status_t res = _OperationError(OpReadDir);
391 if (res != B_OK)
392 return res;
394 *cookieVerf = fReply->Stream().GetUHyper();
396 bool isNext;
397 uint32 count = 0;
399 // TODO: using list instead of array would make this much more elegant
400 // and efficient
401 XDR::Stream::Position dataStart = fReply->Stream().Current();
402 isNext = fReply->Stream().GetBoolean();
403 while (isNext) {
404 fReply->Stream().GetUHyper();
406 free(fReply->Stream().GetString());
407 AttrValue* values;
408 uint32 attrCount;
409 _DecodeAttrs(fReply->Stream(), &values, &attrCount);
410 delete[] values;
412 count++;
414 isNext = fReply->Stream().GetBoolean();
417 DirEntry* entries = new(std::nothrow) DirEntry[count];
418 if (entries == NULL)
419 return B_NO_MEMORY;
421 count = 0;
422 fReply->Stream().SetPosition(dataStart);
423 isNext = fReply->Stream().GetBoolean();
424 while (isNext) {
425 *cookie = fReply->Stream().GetUHyper();
427 entries[count].fName = fReply->Stream().GetString();
428 _DecodeAttrs(fReply->Stream(), &entries[count].fAttrs,
429 &entries[count].fAttrCount);
431 count++;
433 isNext = fReply->Stream().GetBoolean();
435 *eof = fReply->Stream().GetBoolean();
437 *_count = count;
438 *dirents = entries;
440 if (fReply->Stream().IsEOF()) {
441 delete[] entries;
442 return B_BAD_VALUE;
445 return B_OK;
449 status_t
450 ReplyInterpreter::ReadLink(void* buffer, uint32* size, uint32 maxSize)
452 status_t res = _OperationError(OpReadLink);
453 if (res != B_OK)
454 return res;
456 const void* ptr = fReply->Stream().GetOpaque(size);
457 memcpy(buffer, ptr, min_c(*size, maxSize));
459 return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
463 status_t
464 ReplyInterpreter::Remove(uint64* before, uint64* after, bool& atomic)
466 status_t res = _OperationError(OpRemove);
467 if (res != B_OK)
468 return res;
470 atomic = fReply->Stream().GetBoolean();
471 *before = fReply->Stream().GetUHyper();
472 *after = fReply->Stream().GetUHyper();
474 return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
478 status_t
479 ReplyInterpreter::Rename(uint64* fromBefore, uint64* fromAfter,
480 bool& fromAtomic, uint64* toBefore, uint64* toAfter, bool& toAtomic)
482 status_t res = _OperationError(OpRename);
483 if (res != B_OK)
484 return res;
486 fromAtomic = fReply->Stream().GetBoolean();
487 *fromBefore = fReply->Stream().GetUHyper();
488 *fromAfter = fReply->Stream().GetUHyper();
490 toAtomic = fReply->Stream().GetBoolean();
491 *toBefore = fReply->Stream().GetUHyper();
492 *toAfter = fReply->Stream().GetUHyper();
493 return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
497 status_t
498 ReplyInterpreter::SetAttr()
500 status_t res = _OperationError(OpSetAttr);
501 if (res != B_OK)
502 return res;
504 uint32 bcount = fReply->Stream().GetUInt();
505 for (uint32 i = 0; i < bcount; i++)
506 fReply->Stream().GetUInt();
508 return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
512 status_t
513 ReplyInterpreter::SetClientID(uint64* clientid, uint64* verifier)
515 status_t res = _OperationError(OpSetClientID);
516 if (res != B_OK)
517 return res;
519 *clientid = fReply->Stream().GetUHyper();
520 *verifier = fReply->Stream().GetUHyper();
522 return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
526 status_t
527 ReplyInterpreter::Write(uint32* size)
529 status_t res = _OperationError(OpWrite);
530 if (res != B_OK)
531 return res;
533 *size = fReply->Stream().GetUInt();
534 fReply->Stream().GetInt();
535 fReply->Stream().GetUHyper();
537 return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
541 const char**
542 ReplyInterpreter::_GetPath(XDR::ReadStream& stream)
544 uint32 count = stream.GetUInt();
545 char** path = new char*[count + 1];
546 if (path == NULL)
547 return NULL;
549 uint32 i;
550 for (i = 0; i < count; i++) {
551 path[i] = stream.GetString();
552 if (path[i] == NULL)
553 goto out;
555 path[count] = NULL;
557 return const_cast<const char**>(path);
559 out:
560 for (uint32 j = 0; j < i; j++)
561 free(path[i]);
562 delete[] path;
563 return NULL;
567 status_t
568 ReplyInterpreter::_DecodeAttrs(XDR::ReadStream& str, AttrValue** attrs,
569 uint32* count)
571 uint32 bcount = fReply->Stream().GetUInt();
572 uint32* bitmap = new(std::nothrow) uint32[bcount];
573 if (bitmap == NULL)
574 return B_NO_MEMORY;
575 ArrayDeleter<uint32> _(bitmap);
577 uint32 attr_count = 0;
578 for (uint32 i = 0; i < bcount; i++) {
579 bitmap[i] = str.GetUInt();
580 attr_count += CountBits(bitmap[i]);
583 if (attr_count == 0) {
584 *attrs = NULL;
585 *count = 0;
586 return B_OK;
587 } else if (attr_count > FATTR4_MAXIMUM_ATTR_ID)
588 return B_BAD_VALUE;
590 uint32 size;
591 const void* ptr = str.GetOpaque(&size);
592 XDR::ReadStream stream(const_cast<void*>(ptr), size);
594 AttrValue* values = new(std::nothrow) AttrValue[attr_count];
595 if (values == NULL)
596 return B_NO_MEMORY;
598 uint32 current = 0;
600 if (sIsAttrSet(FATTR4_SUPPORTED_ATTRS, bitmap, bcount)) {
601 values[current].fAttribute = FATTR4_SUPPORTED_ATTRS;
602 uint32 count = stream.GetInt();
603 uint32 i;
604 // two uint32 are enough for NFS4, not for NFS4.1
605 for (i = 0; i < min_c(count, 2); i++)
606 ((uint32*)&values[current].fData.fValue64)[i] = stream.GetUInt();
607 for (; i < count; i++)
608 stream.GetUInt();
609 current++;
612 if (sIsAttrSet(FATTR4_TYPE, bitmap, bcount)) {
613 values[current].fAttribute = FATTR4_TYPE;
614 values[current].fData.fValue32 = stream.GetInt();
615 current++;
618 if (sIsAttrSet(FATTR4_FH_EXPIRE_TYPE, bitmap, bcount)) {
619 values[current].fAttribute = FATTR4_FH_EXPIRE_TYPE;
620 values[current].fData.fValue32 = stream.GetUInt();
621 current++;
624 if (sIsAttrSet(FATTR4_CHANGE, bitmap, bcount)) {
625 values[current].fAttribute = FATTR4_CHANGE;
626 values[current].fData.fValue64 = stream.GetUHyper();
627 current++;
630 if (sIsAttrSet(FATTR4_SIZE, bitmap, bcount)) {
631 values[current].fAttribute = FATTR4_SIZE;
632 values[current].fData.fValue64 = stream.GetUHyper();
633 current++;
636 if (sIsAttrSet(FATTR4_FSID, bitmap, bcount)) {
637 values[current].fAttribute = FATTR4_FSID;
638 values[current].fFreePointer = true;
640 FileSystemId fsid;
641 fsid.fMajor = stream.GetUHyper();
642 fsid.fMinor = stream.GetUHyper();
644 values[current].fData.fPointer = malloc(sizeof(fsid));
645 memcpy(values[current].fData.fPointer, &fsid, sizeof(fsid));
646 current++;
649 if (sIsAttrSet(FATTR4_LEASE_TIME, bitmap, bcount)) {
650 values[current].fAttribute = FATTR4_LEASE_TIME;
651 values[current].fData.fValue32 = stream.GetUInt();
652 current++;
655 if (sIsAttrSet(FATTR4_FILEID, bitmap, bcount)) {
656 values[current].fAttribute = FATTR4_FILEID;
657 values[current].fData.fValue64 = stream.GetUHyper();
658 current++;
661 if (sIsAttrSet(FATTR4_FILES_FREE, bitmap, bcount)) {
662 values[current].fAttribute = FATTR4_FILES_FREE;
663 values[current].fData.fValue64 = stream.GetUHyper();
664 current++;
667 if (sIsAttrSet(FATTR4_FILES_TOTAL, bitmap, bcount)) {
668 values[current].fAttribute = FATTR4_FILES_TOTAL;
669 values[current].fData.fValue64 = stream.GetUHyper();
670 current++;
673 if (sIsAttrSet(FATTR4_FS_LOCATIONS, bitmap, bcount)) {
674 values[current].fAttribute = FATTR4_FS_LOCATIONS;
676 FSLocations* locs = new FSLocations;
677 locs->fRootPath = _GetPath(stream);
678 locs->fCount = stream.GetUInt();
679 locs->fLocations = new FSLocation[locs->fCount];
680 for (uint32 i = 0; i < locs->fCount; i++) {
681 locs->fLocations[i].fRootPath = _GetPath(stream);
682 locs->fLocations[i].fCount = stream.GetUInt();
683 locs->fLocations[i].fLocations
684 = new const char*[locs->fLocations[i].fCount];
685 for (uint32 j = 0; j < locs->fLocations[i].fCount; j++)
686 locs->fLocations[i].fLocations[j] = stream.GetString();
688 values[current].fData.fLocations = locs;
689 current++;
692 if (sIsAttrSet(FATTR4_MAXREAD, bitmap, bcount)) {
693 values[current].fAttribute = FATTR4_MAXREAD;
694 values[current].fData.fValue64 = stream.GetUHyper();
695 current++;
698 if (sIsAttrSet(FATTR4_MAXWRITE, bitmap, bcount)) {
699 values[current].fAttribute = FATTR4_MAXWRITE;
700 values[current].fData.fValue64 = stream.GetUHyper();
701 current++;
704 if (sIsAttrSet(FATTR4_MODE, bitmap, bcount)) {
705 values[current].fAttribute = FATTR4_MODE;
706 values[current].fData.fValue32 = stream.GetUInt();
707 current++;
710 if (sIsAttrSet(FATTR4_NUMLINKS, bitmap, bcount)) {
711 values[current].fAttribute = FATTR4_NUMLINKS;
712 values[current].fData.fValue32 = stream.GetUInt();
713 current++;
716 if (sIsAttrSet(FATTR4_OWNER, bitmap, bcount)) {
717 values[current].fAttribute = FATTR4_OWNER;
718 values[current].fFreePointer = true;
719 values[current].fData.fPointer = stream.GetString();
720 current++;
723 if (sIsAttrSet(FATTR4_OWNER_GROUP, bitmap, bcount)) {
724 values[current].fAttribute = FATTR4_OWNER_GROUP;
725 values[current].fFreePointer = true;
726 values[current].fData.fPointer = stream.GetString();
727 current++;
730 if (sIsAttrSet(FATTR4_SPACE_FREE, bitmap, bcount)) {
731 values[current].fAttribute = FATTR4_SPACE_FREE;
732 values[current].fData.fValue64 = stream.GetUHyper();
733 current++;
736 if (sIsAttrSet(FATTR4_SPACE_TOTAL, bitmap, bcount)) {
737 values[current].fAttribute = FATTR4_SPACE_TOTAL;
738 values[current].fData.fValue64 = stream.GetUHyper();
739 current++;
742 if (sIsAttrSet(FATTR4_TIME_ACCESS, bitmap, bcount)) {
743 values[current].fAttribute = FATTR4_TIME_ACCESS;
744 values[current].fFreePointer = true;
746 struct timespec ts;
747 ts.tv_sec = static_cast<time_t>(stream.GetHyper());
748 ts.tv_nsec = static_cast<long>(stream.GetUInt());
750 values[current].fData.fPointer = malloc(sizeof(ts));
751 memcpy(values[current].fData.fPointer, &ts, sizeof(ts));
752 current++;
755 if (sIsAttrSet(FATTR4_TIME_CREATE, bitmap, bcount)) {
756 values[current].fAttribute = FATTR4_TIME_CREATE;
757 values[current].fFreePointer = true;
759 struct timespec ts;
760 ts.tv_sec = static_cast<time_t>(stream.GetHyper());
761 ts.tv_nsec = static_cast<long>(stream.GetUInt());
763 values[current].fData.fPointer = malloc(sizeof(ts));
764 memcpy(values[current].fData.fPointer, &ts, sizeof(ts));
765 current++;
768 if (sIsAttrSet(FATTR4_TIME_METADATA, bitmap, bcount)) {
769 values[current].fAttribute = FATTR4_TIME_METADATA;
770 values[current].fFreePointer = true;
772 struct timespec ts;
773 ts.tv_sec = static_cast<time_t>(stream.GetHyper());
774 ts.tv_nsec = static_cast<long>(stream.GetUInt());
776 values[current].fData.fPointer = malloc(sizeof(ts));
777 memcpy(values[current].fData.fPointer, &ts, sizeof(ts));
778 current++;
781 if (sIsAttrSet(FATTR4_TIME_MODIFY, bitmap, bcount)) {
782 values[current].fAttribute = FATTR4_TIME_MODIFY;
783 values[current].fFreePointer = true;
785 struct timespec ts;
786 ts.tv_sec = static_cast<time_t>(stream.GetHyper());
787 ts.tv_nsec = static_cast<long>(stream.GetUInt());
789 values[current].fData.fPointer = malloc(sizeof(ts));
790 memcpy(values[current].fData.fPointer, &ts, sizeof(ts));
791 current++;
794 *count = attr_count;
795 *attrs = values;
796 if (str.IsEOF()) {
797 delete[] values;
798 return B_BAD_VALUE;
800 return B_OK;
804 status_t
805 ReplyInterpreter::_OperationError(Opcode op)
807 if (fDecodeError)
808 return B_BAD_VALUE;
810 if (fReply == NULL)
811 return B_NOT_INITIALIZED;
813 if (fReply->Error() != B_OK || fReply->Stream().IsEOF()) {
814 fDecodeError = true;
815 return fReply->Error();
818 if (fReply->Stream().GetInt() != op) {
819 fDecodeError = true;
820 return B_BAD_VALUE;
823 status_t result = _NFS4ErrorToHaiku(fReply->Stream().GetUInt());
824 if (result != B_OK)
825 fDecodeError = true;
826 return result;
830 status_t
831 ReplyInterpreter::_NFS4ErrorToHaiku(uint32 x)
833 switch (x) {
834 case NFS4_OK: return B_OK;
835 case NFS4ERR_PERM: return B_PERMISSION_DENIED;
836 case NFS4ERR_NOENT: return B_ENTRY_NOT_FOUND;
837 case NFS4ERR_IO: return B_IO_ERROR;
838 case NFS4ERR_NXIO: return B_DEVICE_NOT_FOUND;
839 case NFS4ERR_ACCESS: return B_NOT_ALLOWED;
840 case NFS4ERR_EXIST: return B_FILE_EXISTS;
841 case NFS4ERR_XDEV: return B_CROSS_DEVICE_LINK;
842 case NFS4ERR_NOTDIR: return B_NOT_A_DIRECTORY;
843 case NFS4ERR_ISDIR: return B_IS_A_DIRECTORY;
844 case NFS4ERR_INVAL: return B_BAD_VALUE;
845 case NFS4ERR_FBIG: return B_FILE_TOO_LARGE;
846 case NFS4ERR_NOTSUPP: return B_UNSUPPORTED;
847 case NFS4ERR_ROFS: return B_READ_ONLY_DEVICE;
848 case NFS4ERR_NAMETOOLONG: return B_NAME_TOO_LONG;
849 case NFS4ERR_NOTEMPTY: return B_DIRECTORY_NOT_EMPTY;
850 // ...
851 case NFS4ERR_DELAY:
852 case NFS4ERR_DENIED:
853 case NFS4ERR_LOCKED:
854 case NFS4ERR_GRACE:
855 return B_WOULD_BLOCK;
857 case NFS4ERR_STALE:
858 case NFS4ERR_FHEXPIRED:
859 return B_FILE_NOT_FOUND;
860 // ...
861 default: return B_ERROR;