1258882Semaste/*
2258882Semaste * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3353358Sdim * Distributed under the terms of the MIT License.
4353358Sdim */
5353358Sdim
6258882Semaste
7258882Semaste#include "UnpackingAttributeDirectoryCookie.h"
8258882Semaste
9258882Semaste#include "DebugSupport.h"
10353358Sdim#include "PackageNode.h"
11258882Semaste#include "Utils.h"
12258882Semaste
13288943Sdim
14288943SdimUnpackingAttributeDirectoryCookie::UnpackingAttributeDirectoryCookie(
15258882Semaste	PackageNode* packageNode)
16314564Sdim	:
17258882Semaste	fPackageNode(packageNode),
18327952Sdim	fAttribute(NULL),
19341825Sdim	fState(AUTO_PACKAGE_ATTRIBUTE_ENUM_FIRST)
20321369Sdim{
21258882Semaste	if (fPackageNode != NULL) {
22321369Sdim		fPackageNode->AcquireReference();
23321369Sdim		fAttribute = fPackageNode->Attributes().Head();
24288943Sdim	}
25288943Sdim}
26258882Semaste
27258882Semaste
28258882SemasteUnpackingAttributeDirectoryCookie::~UnpackingAttributeDirectoryCookie()
29258882Semaste{
30258882Semaste	if (fPackageNode != NULL)
31353358Sdim		fPackageNode->ReleaseReference();
32314564Sdim}
33314564Sdim
34314564Sdim
35314564Sdim/*static*/ status_t
36314564SdimUnpackingAttributeDirectoryCookie::Open(PackageNode* packageNode,
37314564Sdim	AttributeDirectoryCookie*& _cookie)
38258882Semaste{
39314564Sdim	UnpackingAttributeDirectoryCookie* cookie = new(std::nothrow)
40314564Sdim		UnpackingAttributeDirectoryCookie(packageNode);
41314564Sdim	if (cookie == NULL)
42314564Sdim		return B_NO_MEMORY;
43314564Sdim
44314564Sdim	_cookie = cookie;
45314564Sdim	return B_OK;
46314564Sdim}
47258882Semaste
48258882Semaste
49258882Semastestatus_t
50258882SemasteUnpackingAttributeDirectoryCookie::Read(dev_t volumeID, ino_t nodeID,
51353358Sdim	struct dirent* buffer, size_t bufferSize, uint32* _count)
52341825Sdim{
53314564Sdim	uint32 maxCount = *_count;
54314564Sdim	uint32 count = 0;
55314564Sdim
56314564Sdim	dirent* previousEntry = NULL;
57314564Sdim
58314564Sdim	while (fState < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT || fAttribute != NULL) {
59314564Sdim		// don't read more entries than requested
60314564Sdim		if (count >= maxCount)
61314564Sdim			break;
62314564Sdim
63314564Sdim		// align the buffer for subsequent entries
64341825Sdim		if (count > 0) {
65258882Semaste			addr_t offset = (addr_t)buffer % 8;
66258882Semaste			if (offset > 0) {
67314564Sdim				offset = 8 - offset;
68353358Sdim				if (bufferSize <= offset)
69353358Sdim					break;
70353358Sdim
71314564Sdim				previousEntry->d_reclen += offset;
72314564Sdim				buffer = (dirent*)((addr_t)buffer + offset);
73314564Sdim				bufferSize -= offset;
74314564Sdim			}
75353358Sdim		}
76353358Sdim
77353358Sdim		// get the attribute name
78314564Sdim		const char* name;
79258882Semaste		if (fState < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT) {
80258882Semaste			name = AutoPackageAttributes::NameForAttribute(
81314564Sdim				(AutoPackageAttribute)fState);
82314564Sdim		} else
83314564Sdim			name = fAttribute->Name();
84353358Sdim
85353358Sdim		// fill in the entry name -- checks whether the entry fits into the
86353358Sdim		// buffer
87353358Sdim		if (!set_dirent_name(buffer, bufferSize, name, strlen(name))) {
88353358Sdim			if (count == 0)
89353358Sdim				RETURN_ERROR(B_BUFFER_OVERFLOW);
90314564Sdim			break;
91258882Semaste		}
92258882Semaste
93314564Sdim		// fill in the other data
94353358Sdim		buffer->d_dev = volumeID;
95353358Sdim		buffer->d_ino = nodeID;
96314564Sdim
97353358Sdim		count++;
98314564Sdim		previousEntry = buffer;
99258882Semaste		bufferSize -= buffer->d_reclen;
100258882Semaste		buffer = (dirent*)((addr_t)buffer + buffer->d_reclen);
101314564Sdim
102353358Sdim		if (fState < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT)
103353358Sdim			fState++;
104353358Sdim		else
105314564Sdim			fAttribute = fPackageNode->Attributes().GetNext(fAttribute);
106314564Sdim	}
107314564Sdim
108314564Sdim	*_count = count;
109258882Semaste	return B_OK;
110258882Semaste}
111314564Sdim
112353358Sdim
113353358Sdimstatus_t
114314564SdimUnpackingAttributeDirectoryCookie::Rewind()
115258882Semaste{
116258882Semaste	if (fPackageNode != NULL)
117314564Sdim		fAttribute = fPackageNode->Attributes().Head();
118314564Sdim
119314564Sdim	fState = AUTO_PACKAGE_ATTRIBUTE_ENUM_FIRST;
120353358Sdim
121353358Sdim	return B_OK;
122353358Sdim}
123353358Sdim