xref: /haiku/src/apps/haikudepot/server/PopulatePkgSizesProcess.cpp (revision 344ded80d400028c8f561b4b876257b94c12db4a)
1 /*
2  * Copyright 2018-2024, Andrew Lindesay <apl@lindesay.co.nz>.
3 
4  * All rights reserved. Distributed under the terms of the MIT License.
5  *
6  * Note that this file included code earlier from `MainWindow.cpp` and
7  * copyrights have been latterly been carried across in 2021.
8  */
9 
10 
11 #include "PopulatePkgSizesProcess.h"
12 
13 #include <Catalog.h>
14 
15 #include "Logger.h"
16 #include "PackageKitUtils.h"
17 #include "PackageUtils.h"
18 
19 
20 #undef B_TRANSLATION_CONTEXT
21 #define B_TRANSLATION_CONTEXT "PopulatePkgSizesProcess"
22 
23 
24 PopulatePkgSizesProcess::PopulatePkgSizesProcess(Model* model)
25 	:
26 	fModel(model)
27 {
28 }
29 
30 
31 PopulatePkgSizesProcess::~PopulatePkgSizesProcess()
32 {
33 }
34 
35 
36 const char*
37 PopulatePkgSizesProcess::Name() const
38 {
39 	return "PopulatePkgSizesProcess";
40 }
41 
42 
43 const char*
44 PopulatePkgSizesProcess::Description() const
45 {
46 	return B_TRANSLATE("Populating package sizes");
47 }
48 
49 
50 status_t
51 PopulatePkgSizesProcess::RunInternal()
52 {
53 	int32 countPkgs = 0;
54 	int32 countPkgSized = 0;
55 	int32 countPkgUnsized = 0;
56 
57 	HDINFO("[%s] will populate size for pkgs without a size", Name());
58 
59 	for (int32 d = 0; d < fModel->CountDepots() && !WasStopped(); d++) {
60 		DepotInfoRef depotInfo = fModel->DepotAtIndex(d);
61 		countPkgs += depotInfo->CountPackages();
62 
63 		for (int32 p = 0; p < depotInfo->CountPackages(); p++) {
64 			PackageInfoRef packageInfo = depotInfo->PackageAtIndex(p);
65 
66 			if (!packageInfo.IsSet())
67 				HDFATAL("package is not set");
68 
69 			PackageLocalInfoRef localInfo = PackageUtils::NewLocalInfo(packageInfo);
70 			PackageState state = localInfo->State();
71 
72 			if (localInfo->Size() <= 0 && (state == ACTIVATED || state == INSTALLED)) {
73 				off_t derivedSize = _DeriveSize(packageInfo);
74 
75 				if (derivedSize > 0) {
76 					localInfo->SetSize(derivedSize);
77 					countPkgSized++;
78 					HDDEBUG("[%s] did derive a size for package [%s]", Name(),
79 						packageInfo->Name().String());
80 				} else {
81 					countPkgUnsized++;
82 					HDDEBUG("[%s] unable to derive a size for package [%s]", Name(),
83 						packageInfo->Name().String());
84 				}
85 			}
86 
87 			packageInfo->SetLocalInfo(localInfo);
88 		}
89 	}
90 
91 	HDINFO("[%s] did populate size for %" B_PRId32 " packages with %" B_PRId32
92 		" already having a size and %" B_PRId32 " unable to derive a size",
93 		Name(), countPkgSized, countPkgs - countPkgSized, countPkgUnsized);
94 
95 	return B_OK;
96 }
97 
98 
99 off_t
100 PopulatePkgSizesProcess::_DeriveSize(const PackageInfoRef package) const
101 {
102 	BPath path;
103 	if (PackageKitUtils::DeriveLocalFilePath(package, path) == B_OK) {
104 		BEntry entry(path.Path());
105 		struct stat s = {};
106 		if (entry.GetStat(&s) == B_OK)
107 			return s.st_size;
108 		else
109 			HDDEBUG("unable to get the size of local file [%s]", path.Path());
110 	} else {
111 		HDDEBUG("unable to get the local file of package [%s]", package->Name().String());
112 	}
113 	return 0;
114 }