xref: /haiku/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingAttributeDirectoryCookie.cpp (revision f5821a1aee77d3b9a979b42c68a79e50b5ebaefe)
1 /*
2  * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "UnpackingAttributeDirectoryCookie.h"
8 
9 #include "DebugSupport.h"
10 #include "PackageNode.h"
11 #include "Utils.h"
12 
13 
14 UnpackingAttributeDirectoryCookie::UnpackingAttributeDirectoryCookie(
15 	PackageNode* packageNode)
16 	:
17 	fPackageNode(packageNode),
18 	fAttribute(NULL),
19 	fState(AUTO_PACKAGE_ATTRIBUTE_ENUM_FIRST)
20 {
21 	if (fPackageNode != NULL) {
22 		fPackageNode->AcquireReference();
23 		fAttribute = fPackageNode->Attributes().Head();
24 	}
25 }
26 
27 
28 UnpackingAttributeDirectoryCookie::~UnpackingAttributeDirectoryCookie()
29 {
30 	if (fPackageNode != NULL)
31 		fPackageNode->ReleaseReference();
32 }
33 
34 
35 /*static*/ status_t
36 UnpackingAttributeDirectoryCookie::Open(PackageNode* packageNode,
37 	AttributeDirectoryCookie*& _cookie)
38 {
39 	UnpackingAttributeDirectoryCookie* cookie = new(std::nothrow)
40 		UnpackingAttributeDirectoryCookie(packageNode);
41 	if (cookie == NULL)
42 		return B_NO_MEMORY;
43 
44 	_cookie = cookie;
45 	return B_OK;
46 }
47 
48 
49 status_t
50 UnpackingAttributeDirectoryCookie::Read(dev_t volumeID, ino_t nodeID,
51 	struct dirent* buffer, size_t bufferSize, uint32* _count)
52 {
53 	uint32 maxCount = *_count;
54 	uint32 count = 0;
55 
56 	dirent* previousEntry = NULL;
57 
58 	while (fState < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT || fAttribute != NULL) {
59 		// don't read more entries than requested
60 		if (count >= maxCount)
61 			break;
62 
63 		// align the buffer for subsequent entries
64 		if (count > 0) {
65 			addr_t offset = (addr_t)buffer % 8;
66 			if (offset > 0) {
67 				offset = 8 - offset;
68 				if (bufferSize <= offset)
69 					break;
70 
71 				previousEntry->d_reclen += offset;
72 				buffer = (dirent*)((addr_t)buffer + offset);
73 				bufferSize -= offset;
74 			}
75 		}
76 
77 		// get the attribute name
78 		const String& name = fState < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT
79 			? AutoPackageAttributes::NameForAttribute(
80 				(AutoPackageAttribute)fState)
81 			: fAttribute->Name();
82 
83 		// fill in the entry name -- checks whether the entry fits into the
84 		// buffer
85 		if (!set_dirent_name(buffer, bufferSize, name, strlen(name))) {
86 			if (count == 0)
87 				RETURN_ERROR(B_BUFFER_OVERFLOW);
88 			break;
89 		}
90 
91 		// fill in the other data
92 		buffer->d_dev = volumeID;
93 		buffer->d_ino = nodeID;
94 
95 		count++;
96 		previousEntry = buffer;
97 		bufferSize -= buffer->d_reclen;
98 		buffer = (dirent*)((addr_t)buffer + buffer->d_reclen);
99 
100 		if (fState < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT)
101 			fState++;
102 		else
103 			fAttribute = fPackageNode->Attributes().GetNext(fAttribute);
104 	}
105 
106 	*_count = count;
107 	return B_OK;
108 }
109 
110 
111 status_t
112 UnpackingAttributeDirectoryCookie::Rewind()
113 {
114 	if (fPackageNode != NULL)
115 		fAttribute = fPackageNode->Attributes().Head();
116 
117 	fState = AUTO_PACKAGE_ATTRIBUTE_ENUM_FIRST;
118 
119 	return B_OK;
120 }
121