2 * Copyright (c) 2007, Haiku, Inc.
3 * Distributed under the terms of the MIT license.
6 * Ćukasz 'Sil2100' Zemczak <sil2100@vexillium.org>
10 #include "InstalledPackageInfo.h"
15 #include <Directory.h>
17 #include <FindDirectory.h>
20 const char * kPackagesDir
= "packages";
24 info_prepare(const char *filename
, BFile
*file
, BMessage
*info
)
26 if (filename
== NULL
|| file
== NULL
|| info
== NULL
)
30 status_t ret
= find_directory(B_USER_CONFIG_DIRECTORY
, &path
);
32 ret
= path
.Append(kPackagesDir
);
34 ret
= path
.Append(filename
);
36 ret
= file
->SetTo(path
.Path(), B_READ_ONLY
);
38 ret
= info
->Unflatten(file
);
39 if (ret
== B_OK
&& info
->what
!= P_PACKAGE_INFO
)
47 info_get_package_name(const char *filename
, BString
&name
)
51 status_t ret
= info_prepare(filename
, &file
, &info
);
53 ret
= info
.FindString("package_name", &name
);
59 info_get_package_version(const char *filename
, BString
&version
)
63 status_t ret
= info_prepare(filename
, &file
, &info
);
65 ret
= info
.FindString("package_version", &version
);
70 InstalledPackageInfo::InstalledPackageInfo()
81 InstalledPackageInfo::InstalledPackageInfo(const char *packageName
,
82 const char *version
, bool create
)
89 SetTo(packageName
, version
, create
);
93 InstalledPackageInfo::~InstalledPackageInfo()
100 InstalledPackageInfo::InitCheck()
107 InstalledPackageInfo::SetTo(const char *packageName
, const char *version
,
120 if (find_directory(B_USER_CONFIG_DIRECTORY
, &configPath
) != B_OK
) {
125 if (fPathToInfo
.SetTo(configPath
.Path(), kPackagesDir
) != B_OK
) {
130 // Check whether the directory exists
131 BDirectory
packageDir(fPathToInfo
.Path());
132 fStatus
= packageDir
.InitCheck();
133 if (fStatus
== B_ENTRY_NOT_FOUND
) {
135 packageDir
.SetTo(configPath
.Path());
136 if (packageDir
.CreateDirectory(kPackagesDir
, &packageDir
) != B_OK
) {
142 BString filename
= packageName
;
143 filename
<< version
<< ".pdb";
144 if (fPathToInfo
.Append(filename
.String()) != B_OK
) {
149 BFile
package(fPathToInfo
.Path(), B_READ_ONLY
);
150 fStatus
= package
.InitCheck();
151 if (fStatus
== B_OK
) {
152 // The given package exists, so we can unflatten the data to a message
153 // and then pass it further
155 if (info
.Unflatten(&package
) != B_OK
|| info
.what
!= P_PACKAGE_INFO
) {
161 fStatus
= info
.FindString("package_name", &fName
);
162 fStatus
|= info
.FindString("package_desc", &fDescription
);
163 fStatus
|= info
.FindString("package_version", &fVersion
);
164 int64 spaceNeeded
= 0;
165 fStatus
|= info
.FindInt64("package_size", &spaceNeeded
);
166 fSpaceNeeded
= static_cast<uint64
>(spaceNeeded
);
167 fStatus
|= info
.FindInt32("file_count", &count
);
168 if (fStatus
!= B_OK
) {
175 for (i
= 0; i
< count
; i
++) {
176 if (info
.FindString("items", i
, &itemPath
) != B_OK
) {
180 fInstalledItems
.AddItem(new BString(itemPath
)); // Or maybe BPath better?
183 } else if (fStatus
== B_ENTRY_NOT_FOUND
) {
195 InstalledPackageInfo::AddItem(const char *itemName
)
200 return fInstalledItems
.AddItem(new BString(itemName
));
205 InstalledPackageInfo::Uninstall()
211 uint32 i
, count
= fInstalledItems
.CountItems();
215 // Try to remove all entries that are present in the list
216 for (i
= 0; i
< count
; i
++) {
217 iter
= static_cast<BString
*>(fInstalledItems
.ItemAt(count
- i
- 1));
218 ret
= entry
.SetTo(iter
->String());
220 // The entry's directory is locked - wait a few cycles for it to
223 for (tries
= 0; tries
< P_BUSY_TRIES
; tries
++) {
224 ret
= entry
.SetTo(iter
->String());
232 if (ret
== B_ENTRY_NOT_FOUND
)
234 else if (ret
!= B_OK
) {
239 if (entry
.Exists() && entry
.Remove() != B_OK
) {
243 fInstalledItems
.RemoveItem(count
- i
- 1);
246 if (entry
.SetTo(fPathToInfo
.Path()) != B_OK
) {
250 if (entry
.Exists() && entry
.Remove() != B_OK
) {
260 InstalledPackageInfo::Save()
262 // If the package info is not up to date and everything till now was
263 // done correctly, we will save all data as a flattened BMessage to the
265 if (fIsUpToDate
|| fStatus
!= B_OK
)
270 fStatus
= package
.SetTo(fPathToInfo
.Path(), B_WRITE_ONLY
| B_CREATE_FILE
274 fStatus
= package
.SetTo(fPathToInfo
.Path(), B_WRITE_ONLY
| B_ERASE_FILE
);
281 int32 i
, count
= fInstalledItems
.CountItems();
282 BMessage
info(P_PACKAGE_INFO
);
283 ret
= info
.AddString("package_name", fName
);
284 ret
|= info
.AddString("package_desc", fDescription
);
285 ret
|= info
.AddString("package_version", fVersion
);
286 ret
|= info
.AddInt64("package_size", fSpaceNeeded
);
287 ret
|= info
.AddInt32("file_count", count
);
294 for (i
= 0; i
< count
; i
++) {
295 iter
= static_cast<BString
*>(fInstalledItems
.ItemAt(i
));
296 if (info
.AddString("items", *iter
) != B_OK
) {
302 if (info
.Flatten(&package
) != B_OK
) {
316 InstalledPackageInfo::_ClearItemList()
318 for (int32 i
= fInstalledItems
.CountItems() - 1; i
>= 0; i
--)
319 delete static_cast<BString
*>(fInstalledItems
.ItemAtFast(i
));
320 fInstalledItems
.MakeEmpty();