xref: /haiku/src/add-ons/kernel/file_systems/packagefs/nodes/AutoPackageAttributes.cpp (revision d06cbe081b7ea043aea2012359744091de6d604d)
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)
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->VersionedName();
110 			_size = strlen(value) + 1;
111 			_type = B_STRING_TYPE;
112 			return value;
113 		}
114 
115 		case AUTO_PACKAGE_ATTRIBUTE_PACKAGE_FILE:
116 		{
117 			const char* value = package->FileName();
118 			_size = strlen(value) + 1;
119 			_type = B_STRING_TYPE;
120 			return value;
121 		}
122 
123 		default:
124 			return NULL;
125 	}
126 }
127 
128 
129 /*static*/ status_t
130 AutoPackageAttributes::OpenCookie(Package* package, const StringKey& name,
131 	int openMode, AttributeCookie*& _cookie)
132 {
133 	if (package == NULL)
134 		return B_ENTRY_NOT_FOUND;
135 
136 	// get the attribute
137 	AutoPackageAttribute attribute;
138 	if (!AttributeForName(name, attribute))
139 		return B_ENTRY_NOT_FOUND;
140 
141 	// allocate the cookie
142 	AutoPackageAttributeCookie* cookie = new(std::nothrow)
143 		AutoPackageAttributeCookie(package, attribute);
144 	if (cookie == NULL)
145 		RETURN_ERROR(B_NO_MEMORY);
146 
147 	_cookie = cookie;
148 	return B_OK;
149 }
150