xref: /haiku/src/add-ons/kernel/file_systems/packagefs/nodes/AutoPackageAttributes.cpp (revision f5821a1aee77d3b9a979b42c68a79e50b5ebaefe)
1 /*
2  * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "AutoPackageAttributes.h"
8 
9 #include <algorithm>
10 #include <new>
11 
12 #include <TypeConstants.h>
13 
14 #include <AutoDeleter.h>
15 
16 #include "AttributeCookie.h"
17 #include "DebugSupport.h"
18 #include "Package.h"
19 #include "StringConstants.h"
20 
21 
22 class AutoPackageAttributeCookie : public AttributeCookie {
23 public:
24 	AutoPackageAttributeCookie(Package* package, AutoPackageAttribute attribute)
25 		:
26 		fPackage(package),
27 		fAttribute(attribute)
28 	{
29 		fPackage->AcquireReference();
30 	}
31 
32 	virtual ~AutoPackageAttributeCookie()
33 	{
34 		fPackage->ReleaseReference();
35 	}
36 
37 	virtual status_t ReadAttribute(off_t offset, void* buffer,
38 		size_t* bufferSize)
39 	{
40 		// get the attribute
41 		off_t size;
42 		uint32 type;
43 		const void* value = AutoPackageAttributes::GetAttributeValue(fPackage,
44 			fAttribute, size, type);
45 		if (value == NULL)
46 			return B_BAD_VALUE;
47 
48 		// check and clamp offset and size
49 		if (offset < 0 || offset > size)
50 			return B_BAD_VALUE;
51 
52 		size_t toCopy = *bufferSize;
53 		if (offset + toCopy > size)
54 			toCopy = size - offset;
55 
56 		if (toCopy > 0)
57 			memcpy(buffer, (const uint8*)value + offset, toCopy);
58 
59 		*bufferSize = toCopy;
60 		return B_OK;
61 	}
62 
63 	virtual status_t ReadAttributeStat(struct stat* st)
64 	{
65 		if (AutoPackageAttributes::GetAttributeValue(fPackage, fAttribute,
66 			st->st_size, st->st_type) == NULL) {
67 			return B_BAD_VALUE;
68 		}
69 
70 		return B_OK;
71 	}
72 
73 private:
74 	Package*				fPackage;
75 	AutoPackageAttribute	fAttribute;
76 };
77 
78 
79 /*static*/ bool
80 AutoPackageAttributes::AttributeForName(const StringKey& name,
81 	AutoPackageAttribute& _attribute)
82 {
83 	for (int i = 0; i < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT; i++) {
84 		if (name == StringConstants::Get().kAutoPackageAttributeNames[i]) {
85 			_attribute = (AutoPackageAttribute)i;
86 			return true;
87 		}
88 	}
89 
90 	return false;
91 }
92 
93 
94 /*static*/ const String&
95 AutoPackageAttributes::NameForAttribute(AutoPackageAttribute attribute)
96 {
97 	ASSERT(attribute >= 0 && attribute < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT);
98 	return StringConstants::Get().kAutoPackageAttributeNames[attribute];
99 }
100 
101 
102 /*static*/ const void*
103 AutoPackageAttributes::GetAttributeValue(const Package* package,
104 	AutoPackageAttribute attribute, off_t& _size, uint32& _type)
105 {
106 	switch (attribute) {
107 		case AUTO_PACKAGE_ATTRIBUTE_PACKAGE:
108 		{
109 			const char* value = package->FileName();
110 			_size = strlen(value) + 1;
111 			_type = B_STRING_TYPE;
112 			return value;
113 		}
114 
115 		default:
116 			return NULL;
117 	}
118 }
119 
120 
121 /*static*/ status_t
122 AutoPackageAttributes::OpenCookie(Package* package, const StringKey& name,
123 	int openMode, AttributeCookie*& _cookie)
124 {
125 	if (package == NULL)
126 		return B_ENTRY_NOT_FOUND;
127 
128 	// get the attribute
129 	AutoPackageAttribute attribute;
130 	if (!AttributeForName(name, attribute))
131 		return B_ENTRY_NOT_FOUND;
132 
133 	// allocate the cookie
134 	AutoPackageAttributeCookie* cookie = new(std::nothrow)
135 		AutoPackageAttributeCookie(package, attribute);
136 	if (cookie == NULL)
137 		RETURN_ERROR(B_NO_MEMORY);
138 
139 	_cookie = cookie;
140 	return B_OK;
141 }
142