xref: /haiku/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingAttributeDirectoryCookie.cpp (revision 1e7416d9b3846396e2f7d6552e37d72664cd6853)
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 char* name;
79 		if (fState < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT) {
80 			name = AutoPackageAttributes::NameForAttribute(
81 				(AutoPackageAttribute)fState);
82 		} else
83 			name = fAttribute->Name();
84 
85 		// fill in the entry name -- checks whether the entry fits into the
86 		// buffer
87 		if (!set_dirent_name(buffer, bufferSize, name, strlen(name))) {
88 			if (count == 0)
89 				RETURN_ERROR(B_BUFFER_OVERFLOW);
90 			break;
91 		}
92 
93 		// fill in the other data
94 		buffer->d_dev = volumeID;
95 		buffer->d_ino = nodeID;
96 
97 		count++;
98 		previousEntry = buffer;
99 		bufferSize -= buffer->d_reclen;
100 		buffer = (dirent*)((addr_t)buffer + buffer->d_reclen);
101 
102 		if (fState < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT)
103 			fState++;
104 		else
105 			fAttribute = fPackageNode->Attributes().GetNext(fAttribute);
106 	}
107 
108 	*_count = count;
109 	return B_OK;
110 }
111 
112 
113 status_t
114 UnpackingAttributeDirectoryCookie::Rewind()
115 {
116 	if (fPackageNode != NULL)
117 		fAttribute = fPackageNode->Attributes().Head();
118 
119 	fState = AUTO_PACKAGE_ATTRIBUTE_ENUM_FIRST;
120 
121 	return B_OK;
122 }
123