1f2022173SOliver Tappe/*
2f2022173SOliver Tappe * Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
3f2022173SOliver Tappe * Distributed under the terms of the MIT License.
4f2022173SOliver Tappe */
5f2022173SOliver Tappe
6f2022173SOliver Tappe
7f2022173SOliver Tappe#include <package/hpkg/WriterImplBase.h>
8f2022173SOliver Tappe
9f2022173SOliver Tappe#include <errno.h>
10f2022173SOliver Tappe#include <stdio.h>
11f2022173SOliver Tappe#include <stdlib.h>
12f2022173SOliver Tappe#include <string.h>
136a89a36aSIngo Weinhold#include <unistd.h>
14f2022173SOliver Tappe
15f2022173SOliver Tappe#include <algorithm>
16f2022173SOliver Tappe#include <new>
17f2022173SOliver Tappe
18f2022173SOliver Tappe#include <ByteOrder.h>
19e527b796SIngo Weinhold#include <File.h>
20f2022173SOliver Tappe
21f2022173SOliver Tappe#include <AutoDeleter.h>
22b3263ad3SIngo Weinhold#include <ZlibCompressionAlgorithm.h>
2381375d4fSJérôme Duval#ifdef ZSTD_ENABLED
2481375d4fSJérôme Duval#include <ZstdCompressionAlgorithm.h>
2581375d4fSJérôme Duval#endif
26f2022173SOliver Tappe
27f2022173SOliver Tappe#include <package/hpkg/DataReader.h>
28f2022173SOliver Tappe#include <package/hpkg/ErrorOutput.h>
29f2022173SOliver Tappe
301f633814SIngo Weinhold#include <package/hpkg/HPKGDefsPrivate.h>
311f633814SIngo Weinhold
32f2022173SOliver Tappe
33f2022173SOliver Tappenamespace BPackageKit {
34f2022173SOliver Tappe
35f2022173SOliver Tappenamespace BHPKG {
36f2022173SOliver Tappe
37f2022173SOliver Tappenamespace BPrivate {
38f2022173SOliver Tappe
39f2022173SOliver Tappe
40f2022173SOliver Tappe// #pragma mark - AttributeValue
41f2022173SOliver Tappe
42f2022173SOliver Tappe
43f2022173SOliver TappeWriterImplBase::AttributeValue::AttributeValue()
44f2022173SOliver Tappe	:
45f2022173SOliver Tappe	type(B_HPKG_ATTRIBUTE_TYPE_INVALID),
46f2022173SOliver Tappe	encoding(-1)
47f2022173SOliver Tappe{
48f2022173SOliver Tappe}
49f2022173SOliver Tappe
50f2022173SOliver Tappe
51f2022173SOliver TappeWriterImplBase::AttributeValue::~AttributeValue()
52f2022173SOliver Tappe{
53f2022173SOliver Tappe}
54f2022173SOliver Tappe
55f2022173SOliver Tappe
56f2022173SOliver Tappevoid
57f2022173SOliver TappeWriterImplBase::AttributeValue::SetTo(int8 value)
58f2022173SOliver Tappe{
59f2022173SOliver Tappe	signedInt = value;
60f2022173SOliver Tappe	type = B_HPKG_ATTRIBUTE_TYPE_INT;
61f2022173SOliver Tappe}
62f2022173SOliver Tappe
63f2022173SOliver Tappe
64f2022173SOliver Tappevoid
65f2022173SOliver TappeWriterImplBase::AttributeValue::SetTo(uint8 value)
66f2022173SOliver Tappe{
67f2022173SOliver Tappe	unsignedInt = value;
68f2022173SOliver Tappe	type = B_HPKG_ATTRIBUTE_TYPE_UINT;
69f2022173SOliver Tappe}
70f2022173SOliver Tappe
71f2022173SOliver Tappe
72f2022173SOliver Tappevoid
73f2022173SOliver TappeWriterImplBase::AttributeValue::SetTo(int16 value)
74f2022173SOliver Tappe{
75f2022173SOliver Tappe	signedInt = value;
76f2022173SOliver Tappe	type = B_HPKG_ATTRIBUTE_TYPE_INT;
77f2022173SOliver Tappe}
78f2022173SOliver Tappe
79f2022173SOliver Tappe
80f2022173SOliver Tappevoid
81f2022173SOliver TappeWriterImplBase::AttributeValue::SetTo(uint16 value)
82f2022173SOliver Tappe{
83f2022173SOliver Tappe	unsignedInt = value;
84f2022173SOliver Tappe	type = B_HPKG_ATTRIBUTE_TYPE_UINT;
85f2022173SOliver Tappe}
86f2022173SOliver Tappe
87f2022173SOliver Tappe
88f2022173SOliver Tappevoid
89f2022173SOliver TappeWriterImplBase::AttributeValue::SetTo(int32 value)
90f2022173SOliver Tappe{
91f2022173SOliver Tappe	signedInt = value;
92f2022173SOliver Tappe	type = B_HPKG_ATTRIBUTE_TYPE_INT;
93f2022173SOliver Tappe}
94f2022173SOliver Tappe
95f2022173SOliver Tappe
96f2022173SOliver Tappevoid
97f2022173SOliver TappeWriterImplBase::AttributeValue::SetTo(uint32 value)
98f2022173SOliver Tappe{
99f2022173SOliver Tappe	unsignedInt = value;
100f2022173SOliver Tappe	type = B_HPKG_ATTRIBUTE_TYPE_UINT;
101f2022173SOliver Tappe}
102f2022173SOliver Tappe
103f2022173SOliver Tappe
104f2022173SOliver Tappevoid
105f2022173SOliver TappeWriterImplBase::AttributeValue::SetTo(int64 value)
106f2022173SOliver Tappe{
107f2022173SOliver Tappe	signedInt = value;
108f2022173SOliver Tappe	type = B_HPKG_ATTRIBUTE_TYPE_INT;
109f2022173SOliver Tappe}
110f2022173SOliver Tappe
111f2022173SOliver Tappe
112f2022173SOliver Tappevoid
113f2022173SOliver TappeWriterImplBase::AttributeValue::SetTo(uint64 value)
114f2022173SOliver Tappe{
115f2022173SOliver Tappe	unsignedInt = value;
116f2022173SOliver Tappe	type = B_HPKG_ATTRIBUTE_TYPE_UINT;
117f2022173SOliver Tappe}
118f2022173SOliver Tappe
119f2022173SOliver Tappe
120f2022173SOliver Tappevoid
121f2022173SOliver TappeWriterImplBase::AttributeValue::SetTo(CachedString* value)
122f2022173SOliver Tappe{
123f2022173SOliver Tappe	string = value;
124f2022173SOliver Tappe	type = B_HPKG_ATTRIBUTE_TYPE_STRING;
125f2022173SOliver Tappe}
126f2022173SOliver Tappe
127f2022173SOliver Tappe
128f2022173SOliver Tappevoid
129f2022173SOliver TappeWriterImplBase::AttributeValue::SetToData(uint64 size, uint64 offset)
130f2022173SOliver Tappe{
131f2022173SOliver Tappe	data.size = size;
132f2022173SOliver Tappe	data.offset = offset;
133f2022173SOliver Tappe	type = B_HPKG_ATTRIBUTE_TYPE_RAW;
134f2022173SOliver Tappe	encoding = B_HPKG_ATTRIBUTE_ENCODING_RAW_HEAP;
135f2022173SOliver Tappe}
136f2022173SOliver Tappe
137f2022173SOliver Tappe
138f2022173SOliver Tappevoid
139f2022173SOliver TappeWriterImplBase::AttributeValue::SetToData(uint64 size, const void* rawData)
140f2022173SOliver Tappe{
141f2022173SOliver Tappe	data.size = size;
142f2022173SOliver Tappe	if (size > 0)
143f2022173SOliver Tappe		memcpy(data.raw, rawData, size);
144f2022173SOliver Tappe	type = B_HPKG_ATTRIBUTE_TYPE_RAW;
145f2022173SOliver Tappe	encoding = B_HPKG_ATTRIBUTE_ENCODING_RAW_INLINE;
146f2022173SOliver Tappe}
147f2022173SOliver Tappe
148f2022173SOliver Tappe
149f2022173SOliver Tappeuint8
150f2022173SOliver TappeWriterImplBase::AttributeValue::ApplicableEncoding() const
151f2022173SOliver Tappe{
152f2022173SOliver Tappe	switch (type) {
153f2022173SOliver Tappe		case B_HPKG_ATTRIBUTE_TYPE_INT:
154f2022173SOliver Tappe			return _ApplicableIntEncoding(signedInt >= 0
155f2022173SOliver Tappe				? (uint64)signedInt << 1
156f2022173SOliver Tappe				: (uint64)(-(signedInt + 1) << 1));
157f2022173SOliver Tappe		case B_HPKG_ATTRIBUTE_TYPE_UINT:
158f2022173SOliver Tappe			return _ApplicableIntEncoding(unsignedInt);
159f2022173SOliver Tappe		case B_HPKG_ATTRIBUTE_TYPE_STRING:
160f2022173SOliver Tappe			return string->index >= 0
161f2022173SOliver Tappe				? B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE
162f2022173SOliver Tappe				: B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE;
163f2022173SOliver Tappe		case B_HPKG_ATTRIBUTE_TYPE_RAW:
164f2022173SOliver Tappe			return encoding;
165f2022173SOliver Tappe		default:
166f2022173SOliver Tappe			return 0;
167f2022173SOliver Tappe	}
168f2022173SOliver Tappe}
169f2022173SOliver Tappe
170f2022173SOliver Tappe
171f2022173SOliver Tappe/*static*/ uint8
172f2022173SOliver TappeWriterImplBase::AttributeValue::_ApplicableIntEncoding(uint64 value)
173f2022173SOliver Tappe{
174f2022173SOliver Tappe	if (value <= 0xff)
175f2022173SOliver Tappe		return B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT;
176f2022173SOliver Tappe	if (value <= 0xffff)
177f2022173SOliver Tappe		return B_HPKG_ATTRIBUTE_ENCODING_INT_16_BIT;
178f2022173SOliver Tappe	if (value <= 0xffffffff)
179f2022173SOliver Tappe		return B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT;
180f2022173SOliver Tappe
181f2022173SOliver Tappe	return B_HPKG_ATTRIBUTE_ENCODING_INT_64_BIT;
182f2022173SOliver Tappe}
183f2022173SOliver Tappe
184f2022173SOliver Tappe
185f2022173SOliver Tappe// #pragma mark - PackageAttribute
186f2022173SOliver Tappe
1871f633814SIngo Weinhold
18833bc4425SOliver TappeWriterImplBase::PackageAttribute::PackageAttribute(BHPKGAttributeID id_,
189f2022173SOliver Tappe	uint8 type_, uint8 encoding_)
190f2022173SOliver Tappe	:
191f2022173SOliver Tappe	id(id_)
192f2022173SOliver Tappe{
193f2022173SOliver Tappe	type = type_;
194f2022173SOliver Tappe	encoding = encoding_;
195f2022173SOliver Tappe}
196f2022173SOliver Tappe
197f2022173SOliver Tappe
198f2022173SOliver TappeWriterImplBase::PackageAttribute::~PackageAttribute()
199f2022173SOliver Tappe{
200f2022173SOliver Tappe	_DeleteChildren();
201f2022173SOliver Tappe}
202f2022173SOliver Tappe
203f2022173SOliver Tappe
204f2022173SOliver Tappevoid
205f2022173SOliver TappeWriterImplBase::PackageAttribute::AddChild(PackageAttribute* child)
206f2022173SOliver Tappe{
207f2022173SOliver Tappe	children.Add(child);
208f2022173SOliver Tappe}
209f2022173SOliver Tappe
210f2022173SOliver Tappe
211f2022173SOliver Tappevoid
212f2022173SOliver TappeWriterImplBase::PackageAttribute::_DeleteChildren()
213f2022173SOliver Tappe{
214f2022173SOliver Tappe	while (PackageAttribute* child = children.RemoveHead())
215f2022173SOliver Tappe		delete child;
216f2022173SOliver Tappe}
217f2022173SOliver Tappe
218f2022173SOliver Tappe
219f2022173SOliver Tappe// #pragma mark - WriterImplBase
220f2022173SOliver Tappe
221f2022173SOliver Tappe
2221f633814SIngo WeinholdWriterImplBase::WriterImplBase(const char* fileType, BErrorOutput* errorOutput)
223f2022173SOliver Tappe	:
2241f633814SIngo Weinhold	fHeapWriter(NULL),
225b3263ad3SIngo Weinhold	fCompressionAlgorithm(NULL),
226b3263ad3SIngo Weinhold	fCompressionParameters(NULL),
227b3263ad3SIngo Weinhold	fDecompressionAlgorithm(NULL),
228b3263ad3SIngo Weinhold	fDecompressionParameters(NULL),
2291f633814SIngo Weinhold	fFileType(fileType),
230f2022173SOliver Tappe	fErrorOutput(errorOutput),
231f2022173SOliver Tappe	fFileName(NULL),
232796343edSIngo Weinhold	fParameters(),
233e527b796SIngo Weinhold	fFile(NULL),
23444c47711SIngo Weinhold	fOwnsFile(false),
23584297881SIngo Weinhold	fFinished(false)
236f2022173SOliver Tappe{
237f2022173SOliver Tappe}
238f2022173SOliver Tappe
239f2022173SOliver Tappe
240f2022173SOliver TappeWriterImplBase::~WriterImplBase()
241f2022173SOliver Tappe{
2421f633814SIngo Weinhold	delete fHeapWriter;
243b3263ad3SIngo Weinhold	delete fCompressionAlgorithm;
244b3263ad3SIngo Weinhold	delete fCompressionParameters;
245b3263ad3SIngo Weinhold	delete fDecompressionAlgorithm;
246b3263ad3SIngo Weinhold	delete fDecompressionParameters;
2471f633814SIngo Weinhold
24844c47711SIngo Weinhold	if (fOwnsFile)
24944c47711SIngo Weinhold		delete fFile;
250f2022173SOliver Tappe
251327b38d6SIngo Weinhold	if (!fFinished && fFileName != NULL
252796343edSIngo Weinhold		&& (Flags() & B_HPKG_WRITER_UPDATE_PACKAGE) == 0) {
253f2022173SOliver Tappe		unlink(fFileName);
254327b38d6SIngo Weinhold	}
255f2022173SOliver Tappe}
256f2022173SOliver Tappe
257f2022173SOliver Tappe
258f2022173SOliver Tappestatus_t
25944c47711SIngo WeinholdWriterImplBase::Init(BPositionIO* file, bool keepFile, const char* fileName,
260796343edSIngo Weinhold	const BPackageWriterParameters& parameters)
261f2022173SOliver Tappe{
262796343edSIngo Weinhold	fParameters = parameters;
263796343edSIngo Weinhold
264f2022173SOliver Tappe	if (fPackageStringCache.Init() != B_OK)
265f2022173SOliver Tappe		throw std::bad_alloc();
266f2022173SOliver Tappe
26744c47711SIngo Weinhold	if (file == NULL) {
26844c47711SIngo Weinhold		if (fileName == NULL)
26944c47711SIngo Weinhold			return B_BAD_VALUE;
27044c47711SIngo Weinhold
27144c47711SIngo Weinhold		// open file (don't truncate in update mode)
27244c47711SIngo Weinhold		int openMode = O_RDWR;
27344c47711SIngo Weinhold		if ((parameters.Flags() & B_HPKG_WRITER_UPDATE_PACKAGE) == 0)
27444c47711SIngo Weinhold			openMode |= O_CREAT | O_TRUNC;
27544c47711SIngo Weinhold
27644c47711SIngo Weinhold		BFile* newFile = new BFile;
27744c47711SIngo Weinhold		status_t error = newFile->SetTo(fileName, openMode);
27844c47711SIngo Weinhold		if (error != B_OK) {
27944c47711SIngo Weinhold			fErrorOutput->PrintError("Failed to open %s file \"%s\": %s\n",
28044c47711SIngo Weinhold				fFileType, fileName, strerror(errno));
28144c47711SIngo Weinhold			delete newFile;
28244c47711SIngo Weinhold			return error;
28344c47711SIngo Weinhold		}
28444c47711SIngo Weinhold
28544c47711SIngo Weinhold		fFile = newFile;
28644c47711SIngo Weinhold		fOwnsFile = true;
28744c47711SIngo Weinhold	} else {
28844c47711SIngo Weinhold		fFile = file;
28944c47711SIngo Weinhold		fOwnsFile = keepFile;
290f2022173SOliver Tappe	}
291f2022173SOliver Tappe
292f2022173SOliver Tappe	fFileName = fileName;
293f2022173SOliver Tappe
2948f5130edSIngo Weinhold	return B_OK;
2958f5130edSIngo Weinhold}
296b3263ad3SIngo Weinhold
297b3263ad3SIngo Weinhold
2988f5130edSIngo Weinholdstatus_t
2998f5130edSIngo WeinholdWriterImplBase::InitHeapReader(size_t headerSize)
3008f5130edSIngo Weinhold{
3018f5130edSIngo Weinhold	// allocate the compression/decompression algorithm
302b3263ad3SIngo Weinhold	CompressionAlgorithmOwner* compressionAlgorithm = NULL;
3038f5130edSIngo Weinhold	BReference<CompressionAlgorithmOwner> compressionAlgorithmReference;
3048f5130edSIngo Weinhold
3058f5130edSIngo Weinhold	DecompressionAlgorithmOwner* decompressionAlgorithm = NULL;
3068f5130edSIngo Weinhold	BReference<DecompressionAlgorithmOwner> decompressionAlgorithmReference;
3078f5130edSIngo Weinhold
3088f5130edSIngo Weinhold	switch (fParameters.Compression()) {
3098f5130edSIngo Weinhold		case B_HPKG_COMPRESSION_NONE:
3108f5130edSIngo Weinhold			break;
3118f5130edSIngo Weinhold		case B_HPKG_COMPRESSION_ZLIB:
3128f5130edSIngo Weinhold			compressionAlgorithm = CompressionAlgorithmOwner::Create(
3138f5130edSIngo Weinhold				new(std::nothrow) BZlibCompressionAlgorithm,
3148f5130edSIngo Weinhold				new(std::nothrow) BZlibCompressionParameters(
3158f5130edSIngo Weinhold					fParameters.CompressionLevel()));
3168f5130edSIngo Weinhold			compressionAlgorithmReference.SetTo(compressionAlgorithm, true);
3178f5130edSIngo Weinhold
3188f5130edSIngo Weinhold			decompressionAlgorithm = DecompressionAlgorithmOwner::Create(
3198f5130edSIngo Weinhold				new(std::nothrow) BZlibCompressionAlgorithm,
3208f5130edSIngo Weinhold				new(std::nothrow) BZlibDecompressionParameters);
3218f5130edSIngo Weinhold			decompressionAlgorithmReference.SetTo(decompressionAlgorithm, true);
3228f5130edSIngo Weinhold
3238f5130edSIngo Weinhold			if (compressionAlgorithm == NULL
3248f5130edSIngo Weinhold				|| compressionAlgorithm->algorithm == NULL
3258f5130edSIngo Weinhold				|| compressionAlgorithm->parameters == NULL
3268f5130edSIngo Weinhold				|| decompressionAlgorithm == NULL
3278f5130edSIngo Weinhold				|| decompressionAlgorithm->algorithm == NULL
3288f5130edSIngo Weinhold				|| decompressionAlgorithm->parameters == NULL) {
3298f5130edSIngo Weinhold				throw std::bad_alloc();
3308f5130edSIngo Weinhold			}
3318f5130edSIngo Weinhold			break;
33281375d4fSJérôme Duval#ifdef ZSTD_ENABLED
33381375d4fSJérôme Duval		case B_HPKG_COMPRESSION_ZSTD:
33481375d4fSJérôme Duval			compressionAlgorithm = CompressionAlgorithmOwner::Create(
33581375d4fSJérôme Duval				new(std::nothrow) BZstdCompressionAlgorithm,
33681375d4fSJérôme Duval				new(std::nothrow) BZstdCompressionParameters(
33781375d4fSJérôme Duval					fParameters.CompressionLevel()));
33881375d4fSJérôme Duval			compressionAlgorithmReference.SetTo(compressionAlgorithm, true);
33981375d4fSJérôme Duval
34081375d4fSJérôme Duval			decompressionAlgorithm = DecompressionAlgorithmOwner::Create(
34181375d4fSJérôme Duval				new(std::nothrow) BZstdCompressionAlgorithm,
34281375d4fSJérôme Duval				new(std::nothrow) BZstdDecompressionParameters);
34381375d4fSJérôme Duval			decompressionAlgorithmReference.SetTo(decompressionAlgorithm, true);
34481375d4fSJérôme Duval
34581375d4fSJérôme Duval			if (compressionAlgorithm == NULL
34681375d4fSJérôme Duval				|| compressionAlgorithm->algorithm == NULL
34781375d4fSJérôme Duval				|| compressionAlgorithm->parameters == NULL
34881375d4fSJérôme Duval				|| decompressionAlgorithm == NULL
34981375d4fSJérôme Duval				|| decompressionAlgorithm->algorithm == NULL
35081375d4fSJérôme Duval				|| decompressionAlgorithm->parameters == NULL) {
35181375d4fSJérôme Duval				throw std::bad_alloc();
35281375d4fSJérôme Duval			}
35381375d4fSJérôme Duval			break;
35481375d4fSJérôme Duval#endif
3558f5130edSIngo Weinhold		default:
3568f5130edSIngo Weinhold			fErrorOutput->PrintError("Error: Invalid heap compression\n");
3578f5130edSIngo Weinhold			return B_BAD_VALUE;
358b3263ad3SIngo Weinhold	}
359b3263ad3SIngo Weinhold
3601f633814SIngo Weinhold	// create heap writer
361e527b796SIngo Weinhold	fHeapWriter = new PackageFileHeapWriter(fErrorOutput, fFile, headerSize,
362b3263ad3SIngo Weinhold		compressionAlgorithm, decompressionAlgorithm);
3631f633814SIngo Weinhold	fHeapWriter->Init();
3641f633814SIngo Weinhold
365f2022173SOliver Tappe	return B_OK;
366f2022173SOliver Tappe}
367f2022173SOliver Tappe
368f2022173SOliver Tappe
3698f5130edSIngo Weinholdvoid
3708f5130edSIngo WeinholdWriterImplBase::SetCompression(uint32 compression)
3718f5130edSIngo Weinhold{
3728f5130edSIngo Weinhold	fParameters.SetCompression(compression);
3738f5130edSIngo Weinhold}
3748f5130edSIngo Weinhold
3758f5130edSIngo Weinhold
3764ee7d007SOliver Tappevoid
3774ee7d007SOliver TappeWriterImplBase::RegisterPackageInfo(PackageAttributeList& attributeList,
3784ee7d007SOliver Tappe	const BPackageInfo& packageInfo)
3794ee7d007SOliver Tappe{
3804ee7d007SOliver Tappe	// name
381e8533402SIngo Weinhold	AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_NAME, packageInfo.Name(),
382927e0708SIngo Weinhold		attributeList);
3834ee7d007SOliver Tappe
3844ee7d007SOliver Tappe	// summary
385e8533402SIngo Weinhold	AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_SUMMARY,
386927e0708SIngo Weinhold		packageInfo.Summary(), attributeList);
3874ee7d007SOliver Tappe
3884ee7d007SOliver Tappe	// description
389e8533402SIngo Weinhold	AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_DESCRIPTION,
390927e0708SIngo Weinhold		packageInfo.Description(), attributeList);
3914ee7d007SOliver Tappe
3924ee7d007SOliver Tappe	// vendor
393e8533402SIngo Weinhold	AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_VENDOR,
394927e0708SIngo Weinhold		packageInfo.Vendor(), attributeList);
3954ee7d007SOliver Tappe
3964ee7d007SOliver Tappe	// packager
397e8533402SIngo Weinhold	AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_PACKAGER,
398927e0708SIngo Weinhold		packageInfo.Packager(), attributeList);
3994ee7d007SOliver Tappe
40021ee6d5cSIngo Weinhold	// base package (optional)
401927e0708SIngo Weinhold	_AddStringAttributeIfNotEmpty(B_HPKG_ATTRIBUTE_ID_PACKAGE_BASE_PACKAGE,
402927e0708SIngo Weinhold		packageInfo.BasePackage(), attributeList);
4037adfd76bSIngo Weinhold
404d77c6cd2SOliver Tappe	// flags
405d77c6cd2SOliver Tappe	PackageAttribute* flags = new PackageAttribute(
40633bc4425SOliver Tappe		B_HPKG_ATTRIBUTE_ID_PACKAGE_FLAGS, B_HPKG_ATTRIBUTE_TYPE_UINT,
407d77c6cd2SOliver Tappe		B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT);
408d77c6cd2SOliver Tappe	flags->unsignedInt = packageInfo.Flags();
409d77c6cd2SOliver Tappe	attributeList.Add(flags);
410d77c6cd2SOliver Tappe
4114ee7d007SOliver Tappe	// architecture
4124ee7d007SOliver Tappe	PackageAttribute* architecture = new PackageAttribute(
41333bc4425SOliver Tappe		B_HPKG_ATTRIBUTE_ID_PACKAGE_ARCHITECTURE, B_HPKG_ATTRIBUTE_TYPE_UINT,
4144ee7d007SOliver Tappe		B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT);
4154ee7d007SOliver Tappe	architecture->unsignedInt = packageInfo.Architecture();
416d77c6cd2SOliver Tappe	attributeList.Add(architecture);
4174ee7d007SOliver Tappe
4184ee7d007SOliver Tappe	// version
4194ee7d007SOliver Tappe	RegisterPackageVersion(attributeList, packageInfo.Version());
4204ee7d007SOliver Tappe
4214ee7d007SOliver Tappe	// copyright list
422a3e070a7SIngo Weinhold	_AddStringAttributeList(B_HPKG_ATTRIBUTE_ID_PACKAGE_COPYRIGHT,
423a3e070a7SIngo Weinhold			packageInfo.CopyrightList(), attributeList);
4244ee7d007SOliver Tappe
4254ee7d007SOliver Tappe	// license list
426a3e070a7SIngo Weinhold	_AddStringAttributeList(B_HPKG_ATTRIBUTE_ID_PACKAGE_LICENSE,
427a3e070a7SIngo Weinhold		packageInfo.LicenseList(), attributeList);
4284ee7d007SOliver Tappe
429116852feSIngo Weinhold	// URL list
430a3e070a7SIngo Weinhold	_AddStringAttributeList(B_HPKG_ATTRIBUTE_ID_PACKAGE_URL,
431a3e070a7SIngo Weinhold		packageInfo.URLList(), attributeList);
432116852feSIngo Weinhold
433116852feSIngo Weinhold	// source URL list
434a3e070a7SIngo Weinhold	_AddStringAttributeList(B_HPKG_ATTRIBUTE_ID_PACKAGE_SOURCE_URL,
435a3e070a7SIngo Weinhold		packageInfo.SourceURLList(), attributeList);
436116852feSIngo Weinhold
4374ee7d007SOliver Tappe	// provides list
4384ee7d007SOliver Tappe	const BObjectList<BPackageResolvable>& providesList
4394ee7d007SOliver Tappe		= packageInfo.ProvidesList();
4404ee7d007SOliver Tappe	for (int i = 0; i < providesList.CountItems(); ++i) {
4414ee7d007SOliver Tappe		BPackageResolvable* resolvable = providesList.ItemAt(i);
4424ee7d007SOliver Tappe		bool hasVersion = resolvable->Version().InitCheck() == B_OK;
443b2709d8aSIngo Weinhold		bool hasCompatibleVersion
444b2709d8aSIngo Weinhold			= resolvable->CompatibleVersion().InitCheck() == B_OK;
4454ee7d007SOliver Tappe
446e8533402SIngo Weinhold		PackageAttribute* provides = AddStringAttribute(
447927e0708SIngo Weinhold			B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES, resolvable->Name(),
448927e0708SIngo Weinhold			attributeList);
4494ee7d007SOliver Tappe
4504ee7d007SOliver Tappe		if (hasVersion)
4514ee7d007SOliver Tappe			RegisterPackageVersion(provides->children, resolvable->Version());
452b2709d8aSIngo Weinhold
453b2709d8aSIngo Weinhold		if (hasCompatibleVersion) {
454b2709d8aSIngo Weinhold			RegisterPackageVersion(provides->children,
455b2709d8aSIngo Weinhold				resolvable->CompatibleVersion(),
456b2709d8aSIngo Weinhold				B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES_COMPATIBLE);
457b2709d8aSIngo Weinhold		}
4584ee7d007SOliver Tappe	}
4594ee7d007SOliver Tappe
4604ee7d007SOliver Tappe	// requires list
4614ee7d007SOliver Tappe	RegisterPackageResolvableExpressionList(attributeList,
46233bc4425SOliver Tappe		packageInfo.RequiresList(), B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES);
4634ee7d007SOliver Tappe
4644ee7d007SOliver Tappe	// supplements list
4654ee7d007SOliver Tappe	RegisterPackageResolvableExpressionList(attributeList,
46633bc4425SOliver Tappe		packageInfo.SupplementsList(), B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS);
4674ee7d007SOliver Tappe
4684ee7d007SOliver Tappe	// conflicts list
4694ee7d007SOliver Tappe	RegisterPackageResolvableExpressionList(attributeList,
47033bc4425SOliver Tappe		packageInfo.ConflictsList(), B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS);
4714ee7d007SOliver Tappe
4724ee7d007SOliver Tappe	// freshens list
4734ee7d007SOliver Tappe	RegisterPackageResolvableExpressionList(attributeList,
47433bc4425SOliver Tappe		packageInfo.FreshensList(), B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS);
4754ee7d007SOliver Tappe
4764ee7d007SOliver Tappe	// replaces list
477a3e070a7SIngo Weinhold	_AddStringAttributeList(B_HPKG_ATTRIBUTE_ID_PACKAGE_REPLACES,
478a3e070a7SIngo Weinhold		packageInfo.ReplacesList(), attributeList);
4794dcc5232SOliver Tappe
4804489c88bSIngo Weinhold	// global writable file info list
4814489c88bSIngo Weinhold	const BObjectList<BGlobalWritableFileInfo>& globalWritableFileInfos
4824489c88bSIngo Weinhold		= packageInfo.GlobalWritableFileInfos();
4834489c88bSIngo Weinhold	for (int32 i = 0; i < globalWritableFileInfos.CountItems(); ++i) {
4844489c88bSIngo Weinhold		BGlobalWritableFileInfo* info = globalWritableFileInfos.ItemAt(i);
485e8533402SIngo Weinhold		PackageAttribute* attribute = AddStringAttribute(
4864489c88bSIngo Weinhold			B_HPKG_ATTRIBUTE_ID_PACKAGE_GLOBAL_WRITABLE_FILE, info->Path(),
487927e0708SIngo Weinhold			attributeList);
488fe707a23SIngo Weinhold
4894489c88bSIngo Weinhold		if (info->IsDirectory()) {
4904489c88bSIngo Weinhold			PackageAttribute* isDirectoryAttribute = new PackageAttribute(
4914489c88bSIngo Weinhold				B_HPKG_ATTRIBUTE_ID_PACKAGE_IS_WRITABLE_DIRECTORY,
4924489c88bSIngo Weinhold				B_HPKG_ATTRIBUTE_TYPE_UINT,
4934489c88bSIngo Weinhold				B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT);
4944489c88bSIngo Weinhold			isDirectoryAttribute->unsignedInt = 1;
4954489c88bSIngo Weinhold			attribute->children.Add(isDirectoryAttribute);
4964489c88bSIngo Weinhold		}
4974489c88bSIngo Weinhold
498fe707a23SIngo Weinhold		if (info->IsIncluded()) {
499fe707a23SIngo Weinhold			PackageAttribute* updateTypeAttribute = new PackageAttribute(
5004489c88bSIngo Weinhold				B_HPKG_ATTRIBUTE_ID_PACKAGE_WRITABLE_FILE_UPDATE_TYPE,
501fe707a23SIngo Weinhold				B_HPKG_ATTRIBUTE_TYPE_UINT,
502fe707a23SIngo Weinhold				B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT);
503fe707a23SIngo Weinhold			updateTypeAttribute->unsignedInt = info->UpdateType();
504fe707a23SIngo Weinhold			attribute->children.Add(updateTypeAttribute);
505fe707a23SIngo Weinhold		}
506fe707a23SIngo Weinhold	}
507fe707a23SIngo Weinhold
508fe707a23SIngo Weinhold	// user settings file info list
509fe707a23SIngo Weinhold	const BObjectList<BUserSettingsFileInfo>& userSettingsFileInfos
510fe707a23SIngo Weinhold		= packageInfo.UserSettingsFileInfos();
511fe707a23SIngo Weinhold	for (int32 i = 0; i < userSettingsFileInfos.CountItems(); ++i) {
512fe707a23SIngo Weinhold		BUserSettingsFileInfo* info = userSettingsFileInfos.ItemAt(i);
513e8533402SIngo Weinhold		PackageAttribute* attribute = AddStringAttribute(
514927e0708SIngo Weinhold			B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_SETTINGS_FILE, info->Path(),
515927e0708SIngo Weinhold			attributeList);
516927e0708SIngo Weinhold
5174489c88bSIngo Weinhold		if (info->IsDirectory()) {
5184489c88bSIngo Weinhold			PackageAttribute* isDirectoryAttribute = new PackageAttribute(
5194489c88bSIngo Weinhold				B_HPKG_ATTRIBUTE_ID_PACKAGE_IS_WRITABLE_DIRECTORY,
5204489c88bSIngo Weinhold				B_HPKG_ATTRIBUTE_TYPE_UINT,
5214489c88bSIngo Weinhold				B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT);
5224489c88bSIngo Weinhold			isDirectoryAttribute->unsignedInt = 1;
5234489c88bSIngo Weinhold			attribute->children.Add(isDirectoryAttribute);
5244489c88bSIngo Weinhold		} else {
5254489c88bSIngo Weinhold			_AddStringAttributeIfNotEmpty(
5264489c88bSIngo Weinhold				B_HPKG_ATTRIBUTE_ID_PACKAGE_SETTINGS_FILE_TEMPLATE,
5274489c88bSIngo Weinhold				info->TemplatePath(), attribute->children);
5284489c88bSIngo Weinhold		}
529fe707a23SIngo Weinhold	}
530fe707a23SIngo Weinhold
5310f4e11e7SIngo Weinhold	// user list
5320f4e11e7SIngo Weinhold	const BObjectList<BUser>& users = packageInfo.Users();
5330f4e11e7SIngo Weinhold	for (int32 i = 0; i < users.CountItems(); ++i) {
5340f4e11e7SIngo Weinhold		const BUser* user = users.ItemAt(i);
535e8533402SIngo Weinhold		PackageAttribute* attribute = AddStringAttribute(
5360f4e11e7SIngo Weinhold			B_HPKG_ATTRIBUTE_ID_PACKAGE_USER, user->Name(), attributeList);
5370f4e11e7SIngo Weinhold
5380f4e11e7SIngo Weinhold		_AddStringAttributeIfNotEmpty(
5390f4e11e7SIngo Weinhold			B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_REAL_NAME, user->RealName(),
5400f4e11e7SIngo Weinhold			attribute->children);
5410f4e11e7SIngo Weinhold		_AddStringAttributeIfNotEmpty(
5420f4e11e7SIngo Weinhold			B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_HOME, user->Home(),
5430f4e11e7SIngo Weinhold			attribute->children);
5440f4e11e7SIngo Weinhold		_AddStringAttributeIfNotEmpty(
5450f4e11e7SIngo Weinhold			B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_SHELL, user->Shell(),
5460f4e11e7SIngo Weinhold			attribute->children);
5470f4e11e7SIngo Weinhold
5480f4e11e7SIngo Weinhold		for (int32 k = 0; k < user->Groups().CountStrings(); k++) {
549e8533402SIngo Weinhold			AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_GROUP,
5500f4e11e7SIngo Weinhold				user->Groups().StringAt(k), attribute->children);
5510f4e11e7SIngo Weinhold		}
5520f4e11e7SIngo Weinhold	}
5530f4e11e7SIngo Weinhold
5540f4e11e7SIngo Weinhold	// group list
555a3e070a7SIngo Weinhold	_AddStringAttributeList(B_HPKG_ATTRIBUTE_ID_PACKAGE_GROUP,
556a3e070a7SIngo Weinhold		packageInfo.Groups(), attributeList);
5570f4e11e7SIngo Weinhold
558c0ab1409SIngo Weinhold	// post install script list
559a3e070a7SIngo Weinhold	_AddStringAttributeList(B_HPKG_ATTRIBUTE_ID_PACKAGE_POST_INSTALL_SCRIPT,
560a3e070a7SIngo Weinhold		packageInfo.PostInstallScripts(), attributeList);
561c0ab1409SIngo Weinhold
5624dcc5232SOliver Tappe	// checksum (optional, only exists in repositories)
563927e0708SIngo Weinhold	_AddStringAttributeIfNotEmpty(B_HPKG_ATTRIBUTE_ID_PACKAGE_CHECKSUM,
564927e0708SIngo Weinhold		packageInfo.Checksum(), attributeList);
565f19957b8SIngo Weinhold
566f19957b8SIngo Weinhold	// install path (optional)
567927e0708SIngo Weinhold	_AddStringAttributeIfNotEmpty(B_HPKG_ATTRIBUTE_ID_PACKAGE_INSTALL_PATH,
568927e0708SIngo Weinhold		packageInfo.InstallPath(), attributeList);
5694ee7d007SOliver Tappe}
5704ee7d007SOliver Tappe
5714ee7d007SOliver Tappe
5724ee7d007SOliver Tappevoid
5734ee7d007SOliver TappeWriterImplBase::RegisterPackageVersion(PackageAttributeList& attributeList,
574b2709d8aSIngo Weinhold	const BPackageVersion& version, BHPKGAttributeID attributeID)
5754ee7d007SOliver Tappe{
576e8533402SIngo Weinhold	PackageAttribute* versionMajor = AddStringAttribute(attributeID,
577927e0708SIngo Weinhold		version.Major(), attributeList);
5784ee7d007SOliver Tappe
579927e0708SIngo Weinhold	if (!version.Minor().IsEmpty()) {
580e8533402SIngo Weinhold		AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MINOR,
581927e0708SIngo Weinhold			version.Minor(), versionMajor->children);
582927e0708SIngo Weinhold		_AddStringAttributeIfNotEmpty(
583927e0708SIngo Weinhold			B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MICRO, version.Micro(),
584927e0708SIngo Weinhold			versionMajor->children);
585ed6d59a9SIngo Weinhold	}
586ed6d59a9SIngo Weinhold
587927e0708SIngo Weinhold	_AddStringAttributeIfNotEmpty(
588927e0708SIngo Weinhold		B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_PRE_RELEASE,
589927e0708SIngo Weinhold		version.PreRelease(), versionMajor->children);
590927e0708SIngo Weinhold
591202c1daaSIngo Weinhold	if (version.Revision() != 0) {
592202c1daaSIngo Weinhold		PackageAttribute* versionRevision = new PackageAttribute(
593202c1daaSIngo Weinhold			B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_REVISION,
594202c1daaSIngo Weinhold			B_HPKG_ATTRIBUTE_TYPE_UINT, B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT);
595202c1daaSIngo Weinhold		versionRevision->unsignedInt = version.Revision();
596202c1daaSIngo Weinhold		versionMajor->children.Add(versionRevision);
59733bc4425SOliver Tappe	}
5984ee7d007SOliver Tappe}
5994ee7d007SOliver Tappe
6004ee7d007S