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
22class AutoPackageAttributeCookie : public AttributeCookie {
23public:
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
75private:
76	Package*				fPackage;
77	AutoPackageAttribute	fAttribute;
78};
79
80
81/*static*/ bool
82AutoPackageAttributes::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&
97AutoPackageAttributes::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*
105AutoPackageAttributes::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
132AutoPackageAttributes::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