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
20
21static const char* const kAttributeNames[AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT] = {
22	"SYS:PACKAGE"
23};
24
25
26class AutoPackageAttributeCookie : public AttributeCookie {
27public:
28	AutoPackageAttributeCookie(Package* package, AutoPackageAttribute attribute)
29		:
30		fPackage(package),
31		fAttribute(attribute)
32	{
33		fPackage->AcquireReference();
34	}
35
36	virtual ~AutoPackageAttributeCookie()
37	{
38		fPackage->ReleaseReference();
39	}
40
41	virtual status_t ReadAttribute(off_t offset, void* buffer,
42		size_t* bufferSize)
43	{
44		// get the attribute
45		off_t size;
46		uint32 type;
47		const void* value = AutoPackageAttributes::GetAttributeValue(fPackage,
48			fAttribute, size, type);
49		if (value == NULL)
50			return B_BAD_VALUE;
51
52		// check and clamp offset and size
53		if (offset < 0 || offset > size)
54			return B_BAD_VALUE;
55
56		size_t toCopy = *bufferSize;
57		if (offset + toCopy > size)
58			toCopy = size - offset;
59
60		if (toCopy > 0)
61			memcpy(buffer, (const uint8*)value + offset, toCopy);
62
63		*bufferSize = toCopy;
64		return B_OK;
65	}
66
67	virtual status_t ReadAttributeStat(struct stat* st)
68	{
69		if (AutoPackageAttributes::GetAttributeValue(fPackage, fAttribute,
70			st->st_size, st->st_type) == NULL) {
71			return B_BAD_VALUE;
72		}
73
74		return B_OK;
75	}
76
77private:
78	Package*				fPackage;
79	AutoPackageAttribute	fAttribute;
80};
81
82
83/*static*/ bool
84AutoPackageAttributes::AttributeForName(const char* name,
85	AutoPackageAttribute& _attribute)
86{
87	for (int i = 0; i < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT; i++) {
88		if (strcmp(name, kAttributeNames[i]) == 0) {
89			_attribute = (AutoPackageAttribute)i;
90			return true;
91		}
92	}
93
94	return false;
95}
96
97
98/*static*/ const char*
99AutoPackageAttributes::NameForAttribute(AutoPackageAttribute attribute)
100{
101	if (attribute >= 0 && attribute < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT)
102		return kAttributeNames[attribute];
103	return NULL;
104}
105
106
107/*static*/ const void*
108AutoPackageAttributes::GetAttributeValue(const Package* package,
109	AutoPackageAttribute attribute, off_t& _size, uint32& _type)
110{
111	switch (attribute) {
112		case AUTO_PACKAGE_ATTRIBUTE_PACKAGE:
113		{
114			const char* value = package->FileName();
115			_size = strlen(value) + 1;
116			_type = B_STRING_TYPE;
117			return value;
118		}
119
120		default:
121			return NULL;
122	}
123}
124
125
126/*static*/ status_t
127AutoPackageAttributes::OpenCookie(Package* package, const char* name,
128	int openMode, AttributeCookie*& _cookie)
129{
130	if (package == NULL)
131		return B_ENTRY_NOT_FOUND;
132
133	// get the attribute
134	AutoPackageAttribute attribute;
135	if (!AttributeForName(name, attribute))
136		return B_ENTRY_NOT_FOUND;
137
138	// allocate the cookie
139	AutoPackageAttributeCookie* cookie = new(std::nothrow)
140		AutoPackageAttributeCookie(package, attribute);
141	if (cookie == NULL)
142		RETURN_ERROR(B_NO_MEMORY);
143
144	_cookie = cookie;
145	return B_OK;
146}
147