vfs: check userland buffers before reading them.
[haiku.git] / src / kits / tracker / AttributeStream.cpp
blobacad531e72e87944279205accd137eca42eea32e
1 /*
2 Open Tracker License
4 Terms and Conditions
6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
8 Permission is hereby granted, free of charge, to any person obtaining a copy of
9 this software and associated documentation files (the "Software"), to deal in
10 the Software without restriction, including without limitation the rights to
11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12 of the Software, and to permit persons to whom the Software is furnished to do
13 so, subject to the following conditions:
15 The above copyright notice and this permission notice applies to all licensees
16 and shall be included in all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 Except as contained in this notice, the name of Be Incorporated shall not be
26 used in advertising or otherwise to promote the sale, use or other dealings in
27 this Software without prior written authorization from Be Incorporated.
29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30 of Be Incorporated in the United States and other countries. Other brand product
31 names are registered trademarks or trademarks of their respective holders.
32 All rights reserved.
36 #include "AttributeStream.h"
38 #include <Debug.h>
39 #include <Node.h>
41 #include "Utilities.h"
44 // ToDo:
45 // lazy Rewind from Drive, only if data is available
46 // BMessage node
47 // partial feeding (part, not the whole buffer)
50 // #pragma mark - AttributeInfo
53 AttributeInfo::AttributeInfo()
55 fName("")
57 fInfo.type = B_RAW_TYPE;
58 fInfo.size = 0;
62 AttributeInfo::AttributeInfo(const AttributeInfo& other)
64 fName(other.fName),
65 fInfo(other.fInfo)
71 AttributeInfo::AttributeInfo(const char* name, attr_info info)
73 fName(name),
74 fInfo(info)
79 AttributeInfo::AttributeInfo(const char* name, uint32 type, off_t size)
81 fName(name)
83 fInfo.type = type;
84 fInfo.size = size;
88 const char*
89 AttributeInfo::Name() const
91 return fName.String();
95 uint32
96 AttributeInfo::Type() const
98 return fInfo.type;
102 off_t
103 AttributeInfo::Size() const
105 return fInfo.size;
109 void
110 AttributeInfo::SetTo(const AttributeInfo& other)
112 fName = other.fName;
113 fInfo = other.fInfo;
117 void
118 AttributeInfo::SetTo(const char* name, attr_info info)
120 fName = name;
121 fInfo = info;
125 void
126 AttributeInfo::SetTo(const char* name, uint32 type, off_t size)
128 fName = name;
129 fInfo.type = type;
130 fInfo.size = size;
134 // #pragma mark - AttributeStreamNode
137 AttributeStreamNode::AttributeStreamNode()
139 fReadFrom(NULL),
140 fWriteTo(NULL)
145 AttributeStreamNode::~AttributeStreamNode()
147 Detach();
151 AttributeStreamNode&
152 AttributeStreamNode::operator<<(AttributeStreamNode &source)
154 fReadFrom = &source;
155 fReadFrom->fWriteTo = this;
156 if (fReadFrom->CanFeed())
157 fReadFrom->Start();
159 return source;
163 void
164 AttributeStreamNode::Rewind()
166 if (fReadFrom != NULL)
167 fReadFrom->Rewind();
171 void
172 AttributeStreamFileNode::MakeEmpty()
174 TRESPASS();
178 off_t
179 AttributeStreamNode::Contains(const char* name, uint32 type)
181 if (fReadFrom == NULL)
182 return 0;
184 return fReadFrom->Contains(name, type);
188 off_t
189 AttributeStreamNode::Read(const char* name, const char* foreignName,
190 uint32 type, off_t size, void* buffer, void (*swapFunc)(void*))
192 if (fReadFrom == NULL)
193 return 0;
195 return fReadFrom->Read(name, foreignName, type, size, buffer, swapFunc);
199 off_t
200 AttributeStreamNode::Write(const char* name, const char* foreignName,
201 uint32 type, off_t size, const void* buffer)
203 if (fWriteTo == NULL)
204 return 0;
206 return fWriteTo->Write(name, foreignName, type, size, buffer);
210 bool
211 AttributeStreamNode::Drive()
213 ASSERT(CanFeed());
214 if (fReadFrom == NULL)
215 return false;
217 Rewind();
218 return true;
222 const AttributeInfo*
223 AttributeStreamNode::Next()
225 if (fReadFrom != NULL)
226 return fReadFrom->Next();
228 return NULL;
232 const char*
233 AttributeStreamNode::Get()
235 ASSERT(fReadFrom != NULL);
237 return fReadFrom->Get();
241 bool
242 AttributeStreamNode::Fill(char* buffer) const
244 ASSERT(fReadFrom != NULL);
246 return fReadFrom->Fill(buffer);
250 bool
251 AttributeStreamNode::Start()
253 if (fWriteTo == NULL) {
254 // we are at the head of the stream, start drivin'
255 return Drive();
258 return fWriteTo->Start();
262 void
263 AttributeStreamNode::Detach()
265 AttributeStreamNode* tmpFrom = fReadFrom;
266 AttributeStreamNode* tmpTo = fWriteTo;
267 fReadFrom = NULL;
268 fWriteTo = NULL;
270 if (tmpFrom != NULL)
271 tmpFrom->Detach();
273 if (tmpTo != NULL)
274 tmpTo->Detach();
278 // #pragma mark - AttributeStreamFileNode
281 AttributeStreamFileNode::AttributeStreamFileNode()
283 fNode(NULL)
288 AttributeStreamFileNode::AttributeStreamFileNode(BNode* node)
290 fNode(node)
292 ASSERT(fNode != NULL);
296 void
297 AttributeStreamFileNode::Rewind()
299 _inherited::Rewind();
300 fNode->RewindAttrs();
304 void
305 AttributeStreamFileNode::SetTo(BNode* node)
307 fNode = node;
311 off_t
312 AttributeStreamFileNode::Contains(const char* name, uint32 type)
314 ThrowOnAssert(fNode != NULL);
316 attr_info info;
317 if (fNode->GetAttrInfo(name, &info) != B_OK)
318 return 0;
320 if (info.type != type)
321 return 0;
323 return info.size;
327 off_t
328 AttributeStreamFileNode::Read(const char* name, const char* foreignName,
329 uint32 type, off_t size, void* buffer, void (*swapFunc)(void*))
331 if (name != NULL
332 && fNode->ReadAttr(name, type, 0, buffer, (size_t)size) == size) {
333 return size;
336 // didn't find the attribute under the native name, try the foreign name
337 if (foreignName != NULL && fNode->ReadAttr(foreignName, type, 0, buffer,
338 (size_t)size) == size) {
339 // foreign attribute, swap the data
340 if (swapFunc != NULL)
341 (swapFunc)(buffer);
343 return size;
346 return 0;
350 off_t
351 AttributeStreamFileNode::Write(const char* name, const char* foreignName,
352 uint32 type, off_t size, const void* buffer)
354 ThrowOnAssert(fNode != NULL);
356 off_t result = fNode->WriteAttr(name, type, 0, buffer, (size_t)size);
357 if (result == size && foreignName != NULL) {
358 // the write operation worked fine, remove the foreign attribute
359 // to not let stale data hang around
360 fNode->RemoveAttr(foreignName);
363 return result;
367 bool
368 AttributeStreamFileNode::Drive()
370 if (!_inherited::Drive())
371 return false;
373 ThrowOnAssert(fNode != NULL);
375 const AttributeInfo* attr;
376 while ((attr = fReadFrom->Next()) != 0) {
377 const char* data = fReadFrom->Get();
378 off_t result = fNode->WriteAttr(attr->Name(), attr->Type(), 0,
379 data, (size_t)attr->Size());
380 if (result < attr->Size())
381 return true;
384 return true;
388 const char*
389 AttributeStreamFileNode::Get()
391 ASSERT(fNode != NULL);
392 TRESPASS();
394 return NULL;
398 bool
399 AttributeStreamFileNode::Fill(char* buffer) const
401 ThrowOnAssert(fNode != NULL);
403 return fNode->ReadAttr(fCurrentAttr.Name(), fCurrentAttr.Type(), 0,
404 buffer, (size_t)fCurrentAttr.Size()) == (ssize_t)fCurrentAttr.Size();
408 const AttributeInfo*
409 AttributeStreamFileNode::Next()
411 ASSERT(fReadFrom == NULL);
412 ThrowOnAssert(fNode != NULL);
414 char attrName[256];
415 if (fNode->GetNextAttrName(attrName) != B_OK)
416 return NULL;
418 attr_info info;
419 if (fNode->GetAttrInfo(attrName, &info) != B_OK)
420 return NULL;
422 fCurrentAttr.SetTo(attrName, info);
424 return &fCurrentAttr;
428 // #pragma mark - AttributeStreamMemoryNode
431 AttributeStreamMemoryNode::AttributeStreamMemoryNode()
433 fAttributes(5, true),
434 fCurrentIndex(-1)
439 void
440 AttributeStreamMemoryNode::MakeEmpty()
442 fAttributes.MakeEmpty();
446 void
447 AttributeStreamMemoryNode::Rewind()
449 _inherited::Rewind();
450 fCurrentIndex = -1;
454 int32
455 AttributeStreamMemoryNode::Find(const char* name, uint32 type) const
457 int32 count = fAttributes.CountItems();
458 for (int32 index = 0; index < count; index++) {
459 if (strcmp(fAttributes.ItemAt(index)->fAttr.Name(), name) == 0
460 && fAttributes.ItemAt(index)->fAttr.Type() == type) {
461 return index;
465 return -1;
469 off_t
470 AttributeStreamMemoryNode::Contains(const char* name, uint32 type)
472 int32 index = Find(name, type);
474 return index < 0 ? 0 : fAttributes.ItemAt(index)->fAttr.Size();
478 off_t
479 AttributeStreamMemoryNode::Read(const char* name,
480 const char* DEBUG_ONLY(foreignName), uint32 type, off_t bufferSize,
481 void* buffer, void (*DEBUG_ONLY(swapFunc))(void*))
483 ASSERT(foreignName == NULL);
484 ASSERT(swapFunc == NULL);
486 AttrNode* attrNode = NULL;
488 int32 index = Find(name, type);
489 if (index < 0) {
490 if (fReadFrom == NULL)
491 return 0;
493 off_t size = fReadFrom->Contains(name, type);
494 if (size == 0)
495 return 0;
497 attrNode = BufferingGet(name, type, size);
498 if (attrNode == NULL)
499 return 0;
500 } else
501 attrNode = fAttributes.ItemAt(index);
503 if (attrNode->fAttr.Size() > bufferSize)
504 return 0;
506 memcpy(buffer, attrNode->fData, (size_t)attrNode->fAttr.Size());
508 return attrNode->fAttr.Size();
512 off_t
513 AttributeStreamMemoryNode::Write(const char* name, const char*, uint32 type,
514 off_t size, const void* buffer)
516 char* newBuffer = new char[size];
517 memcpy(newBuffer, buffer, (size_t)size);
519 AttrNode* attrNode = new AttrNode(name, type, size, newBuffer);
520 fAttributes.AddItem(attrNode);
522 return size;
526 bool
527 AttributeStreamMemoryNode::Drive()
529 if (!_inherited::Drive())
530 return false;
532 while (BufferingGet())
535 return true;
539 AttributeStreamMemoryNode::AttrNode*
540 AttributeStreamMemoryNode::BufferingGet(const char* name, uint32 type,
541 off_t size)
543 char* newBuffer = new char[size];
544 if (!fReadFrom->Fill(newBuffer)) {
545 delete[] newBuffer;
546 return NULL;
549 AttrNode* attrNode = new AttrNode(name, type, size, newBuffer);
550 fAttributes.AddItem(attrNode);
552 return fAttributes.LastItem();
556 AttributeStreamMemoryNode::AttrNode*
557 AttributeStreamMemoryNode::BufferingGet()
559 if (fReadFrom == NULL)
560 return NULL;
562 const AttributeInfo* attr = fReadFrom->Next();
563 if (attr == NULL)
564 return NULL;
566 return BufferingGet(attr->Name(), attr->Type(), attr->Size());
570 const AttributeInfo*
571 AttributeStreamMemoryNode::Next()
573 if (fReadFrom != NULL) {
574 // the buffer is in the middle of the stream, get
575 // one buffer at a time
576 BufferingGet();
579 if (fCurrentIndex + 1 >= fAttributes.CountItems())
580 return NULL;
582 return &fAttributes.ItemAt(++fCurrentIndex)->fAttr;
586 const char*
587 AttributeStreamMemoryNode::Get()
589 ASSERT(fCurrentIndex < fAttributes.CountItems());
591 return fAttributes.ItemAt(fCurrentIndex)->fData;
595 bool
596 AttributeStreamMemoryNode::Fill(char* buffer) const
598 ASSERT(fCurrentIndex < fAttributes.CountItems());
599 memcpy(buffer, fAttributes.ItemAt(fCurrentIndex)->fData,
600 (size_t)fAttributes.ItemAt(fCurrentIndex)->fAttr.Size());
602 return true;
606 // #pragma mark - AttributeStreamTemplateNode
609 AttributeStreamTemplateNode::AttributeStreamTemplateNode(
610 const AttributeTemplate* attrTemplates, int32 count)
612 fAttributes(attrTemplates),
613 fCurrentIndex(-1),
614 fCount(count)
619 off_t
620 AttributeStreamTemplateNode::Contains(const char* name, uint32 type)
622 int32 index = Find(name, type);
623 if (index < 0)
624 return 0;
626 return fAttributes[index].fSize;
630 void
631 AttributeStreamTemplateNode::Rewind()
633 fCurrentIndex = -1;
637 const AttributeInfo*
638 AttributeStreamTemplateNode::Next()
640 if (fCurrentIndex + 1 >= fCount)
641 return NULL;
643 ++fCurrentIndex;
645 fCurrentAttr.SetTo(fAttributes[fCurrentIndex].fAttributeName,
646 fAttributes[fCurrentIndex].fAttributeType,
647 fAttributes[fCurrentIndex].fSize);
649 return &fCurrentAttr;
653 const char*
654 AttributeStreamTemplateNode::Get()
656 ASSERT(fCurrentIndex < fCount);
658 return fAttributes[fCurrentIndex].fBits;
662 bool
663 AttributeStreamTemplateNode::Fill(char* buffer) const
665 ASSERT(fCurrentIndex < fCount);
666 memcpy(buffer, fAttributes[fCurrentIndex].fBits,
667 (size_t)fAttributes[fCurrentIndex].fSize);
669 return true;
673 int32
674 AttributeStreamTemplateNode::Find(const char* name, uint32 type) const
676 for (int32 index = 0; index < fCount; index++) {
677 if (fAttributes[index].fAttributeType == type &&
678 strcmp(name, fAttributes[index].fAttributeName) == 0) {
679 return index;
683 return -1;
687 // #pragma mark - AttributeStreamFilterNode
690 bool
691 AttributeStreamFilterNode::Reject(const char*, uint32, off_t)
693 // simple pass everything filter
694 return false;
698 const AttributeInfo*
699 AttributeStreamFilterNode::Next()
701 if (fReadFrom == NULL)
702 return NULL;
704 for (;;) {
705 const AttributeInfo* attr = fReadFrom->Next();
706 if (attr == NULL)
707 break;
709 if (!Reject(attr->Name(), attr->Type(), attr->Size()))
710 return attr;
713 return NULL;
717 off_t
718 AttributeStreamFilterNode::Contains(const char* name, uint32 type)
720 if (fReadFrom == NULL)
721 return 0;
723 off_t size = fReadFrom->Contains(name, type);
725 if (!Reject(name, type, size))
726 return size;
728 return 0;
732 off_t
733 AttributeStreamFilterNode::Read(const char* name, const char* foreignName,
734 uint32 type, off_t size, void* buffer, void (*swapFunc)(void*))
736 if (fReadFrom == NULL)
737 return 0;
739 if (!Reject(name, type, size)) {
740 return fReadFrom->Read(name, foreignName, type, size, buffer,
741 swapFunc);
744 return 0;
748 off_t
749 AttributeStreamFilterNode::Write(const char* name, const char* foreignName,
750 uint32 type, off_t size, const void* buffer)
752 if (fWriteTo == NULL)
753 return 0;
755 if (!Reject(name, type, size))
756 return fWriteTo->Write(name, foreignName, type, size, buffer);
758 return size;
762 // #pragma mark - NamesToAcceptAttrFilter
765 NamesToAcceptAttrFilter::NamesToAcceptAttrFilter(const char** nameList)
767 fNameList(nameList)
772 bool
773 NamesToAcceptAttrFilter::Reject(const char* name, uint32, off_t)
775 for (int32 index = 0; ; index++) {
776 if (fNameList[index] == NULL)
777 break;
779 if (strcmp(name, fNameList[index]) == 0) {
780 //PRINT(("filter passing through %s\n", name));
781 return false;
785 //PRINT(("filter rejecting %s\n", name));
786 return true;
790 // #pragma mark - SelectiveAttributeTransformer
793 SelectiveAttributeTransformer::SelectiveAttributeTransformer(
794 const char* attributeName,
795 bool (*transformFunc)(const char* , uint32 , off_t, void*, void*),
796 void* params)
798 fAttributeNameToTransform(attributeName),
799 fTransformFunc(transformFunc),
800 fTransformParams(params),
801 fTransformedBuffers(10, false)
806 SelectiveAttributeTransformer::~SelectiveAttributeTransformer()
808 for (int32 index = fTransformedBuffers.CountItems() - 1; index >= 0;
809 index--) {
810 delete[] fTransformedBuffers.ItemAt(index);
815 void
816 SelectiveAttributeTransformer::Rewind()
818 for (int32 index = fTransformedBuffers.CountItems() - 1; index >= 0;
819 index--) {
820 delete[] fTransformedBuffers.ItemAt(index);
823 fTransformedBuffers.MakeEmpty();
827 off_t
828 SelectiveAttributeTransformer::Read(const char* name, const char* foreignName,
829 uint32 type, off_t size, void* buffer, void (*swapFunc)(void*))
831 if (fReadFrom == NULL)
832 return 0;
834 off_t result = fReadFrom->Read(name, foreignName, type, size, buffer,
835 swapFunc);
837 if (WillTransform(name, type, size, (const char*)buffer))
838 ApplyTransformer(name, type, size, (char*)buffer);
840 return result;
844 bool
845 SelectiveAttributeTransformer::WillTransform(const char* name, uint32, off_t,
846 const char*) const
848 return strcmp(name, fAttributeNameToTransform) == 0;
852 bool
853 SelectiveAttributeTransformer::ApplyTransformer(const char* name, uint32 type,
854 off_t size, char* data)
856 return (fTransformFunc)(name, type, size, data, fTransformParams);
859 char*
860 SelectiveAttributeTransformer::CopyAndApplyTransformer(const char* name,
861 uint32 type, off_t size, const char* data)
863 char* result = NULL;
865 if (data != NULL) {
866 result = new char[size];
867 memcpy(result, data, (size_t)size);
870 if (!(fTransformFunc)(name, type, size, result, fTransformParams)) {
871 delete[] result;
872 return NULL;
875 return result;
879 const AttributeInfo*
880 SelectiveAttributeTransformer::Next()
882 const AttributeInfo* result = fReadFrom->Next();
884 if (result == NULL)
885 return NULL;
887 fCurrentAttr.SetTo(*result);
888 return result;
892 const char*
893 SelectiveAttributeTransformer::Get()
895 if (fReadFrom == NULL)
896 return NULL;
898 const char* result = fReadFrom->Get();
900 if (!WillTransform(fCurrentAttr.Name(), fCurrentAttr.Type(),
901 fCurrentAttr.Size(), result)) {
902 return result;
905 char* transformedData = CopyAndApplyTransformer(fCurrentAttr.Name(),
906 fCurrentAttr.Type(), fCurrentAttr.Size(), result);
908 // enlist for proper disposal when our job is done
909 if (transformedData != NULL) {
910 fTransformedBuffers.AddItem(transformedData);
911 return transformedData;
914 return result;