xref: /haiku/src/add-ons/kernel/file_systems/packagefs/nodes/AutoPackageAttributes.cpp (revision 4bd0c1066b227cec4b79883bdef697c7a27f2e90)
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 + (off_t)toCopy > size)
54 			toCopy = size - offset;
55 
56 		if (toCopy > 0 && user_memcpy(buffer, (const uint8*)value + offset,
57 			toCopy) < B_OK) {
58 			return B_BAD_ADDRESS;
59 		}
60 
61 		*bufferSize = toCopy;
62 		return B_OK;
63 	}
64 
65 	virtual status_t ReadAttributeStat(struct stat* st)
66 	{
67 		if (AutoPackageAttributes::GetAttributeValue(fPackage, fAttribute,
68 			st->st_size, st->st_type) == NULL) {
69 			return B_BAD_VALUE;
70 		}
71 
72 		return B_OK;
73 	}
74 
75 private:
76 	Package*				fPackage;
77 	AutoPackageAttribute	fAttribute;
78 };
79 
80 
81 /*static*/ bool
82 AutoPackageAttributes::AttributeForName(const StringKey& name,
83 	AutoPackageAttribute& _attribute)
84 {
85 	for (int i = 0; i < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT; i++) {
86 		if (name == StringConstants::Get().kAutoPackageAttributeNames[i]) {
87 			_attribute = (AutoPackageAttribute)i;
88 			return true;
89 		}
90 	}
91 
92 	return false;
93 }
94 
95 
96 /*static*/ const String&
97 AutoPackageAttributes::NameForAttribute(AutoPackageAttribute attribute)
98 {
99 	ASSERT(attribute >= 0 && attribute < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT);
100 	return StringConstants::Get().kAutoPackageAttributeNames[attribute];
101 }
102 
103 
104 /*static*/ const void*
105 AutoPackageAttributes::GetAttributeValue(const Package* package,
106 	AutoPackageAttribute attribute, off_t& _size, uint32& _type)
107 {
108 	switch (attribute) {
109 		case AUTO_PACKAGE_ATTRIBUTE_PACKAGE:
110 		{
111 			const char* value = package->VersionedName();
112 			_size = strlen(value) + 1;
113 			_type = B_STRING_TYPE;
114 			return value;
115 		}
116 
117 		case AUTO_PACKAGE_ATTRIBUTE_PACKAGE_FILE:
118 		{
119 			const char* value = package->FileName();
120 			_size = strlen(value) + 1;
121 			_type = B_STRING_TYPE;
122 			return value;
123 		}
124 
125 		default:
126 			return NULL;
127 	}
128 }
129 
130 
131 /*static*/ status_t
132 AutoPackageAttributes::OpenCookie(Package* package, const StringKey& name,
133 	int openMode, AttributeCookie*& _cookie)
134 {
135 	if (package == NULL)
136 		return B_ENTRY_NOT_FOUND;
137 
138 	// get the attribute
139 	AutoPackageAttribute attribute;
140 	if (!AttributeForName(name, attribute))
141 		return B_ENTRY_NOT_FOUND;
142 
143 	// allocate the cookie
144 	AutoPackageAttributeCookie* cookie = new(std::nothrow)
145 		AutoPackageAttributeCookie(package, attribute);
146 	if (cookie == NULL)
147 		RETURN_ERROR(B_NO_MEMORY);
148 
149 	_cookie = cookie;
150 	return B_OK;
151 }
152