1/*
2 * Copyright 2018-2023, 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 "PackageUtils.h"
17
18
19#undef B_TRANSLATION_CONTEXT
20#define B_TRANSLATION_CONTEXT "PopulatePkgSizesProcess"
21
22
23PopulatePkgSizesProcess::PopulatePkgSizesProcess(Model* model)
24	:
25	fModel(model)
26{
27}
28
29
30PopulatePkgSizesProcess::~PopulatePkgSizesProcess()
31{
32}
33
34
35const char*
36PopulatePkgSizesProcess::Name() const
37{
38	return "PopulatePkgSizesProcess";
39}
40
41
42const char*
43PopulatePkgSizesProcess::Description() const
44{
45	return B_TRANSLATE("Populating package sizes");
46}
47
48
49status_t
50PopulatePkgSizesProcess::RunInternal()
51{
52	int32 countPkgs = 0;
53	int32 countPkgSized = 0;
54	int32 countPkgUnsized = 0;
55
56	HDINFO("[%s] will populate size for pkgs without a size", Name());
57
58	for (int32 d = 0; d < fModel->CountDepots() && !WasStopped(); d++) {
59		DepotInfoRef depotInfo = fModel->DepotAtIndex(d);
60		countPkgs += depotInfo->CountPackages();
61
62		for (int32 p = 0; p < depotInfo->CountPackages(); p++) {
63			PackageInfoRef packageInfo = depotInfo->PackageAtIndex(p);
64			PackageState state = packageInfo->State();
65
66			if (packageInfo->Size() <= 0
67					&& (state == ACTIVATED || state == INSTALLED)) {
68				off_t derivedSize = _DeriveSize(packageInfo);
69
70				if (derivedSize > 0) {
71					packageInfo->SetSize(derivedSize);
72					countPkgSized++;
73					HDDEBUG("[%s] did derive a size for package [%s]",
74						Name(), packageInfo->Name().String());
75				} else {
76					countPkgUnsized++;
77					HDDEBUG("[%s] unable to derive a size for package [%s]",
78						Name(), packageInfo->Name().String());
79				}
80			}
81		}
82	}
83
84	HDINFO("[%s] did populate size for %" B_PRId32 " packages with %" B_PRId32
85		" already having a size and %" B_PRId32 " unable to derive a size",
86		Name(), countPkgSized, countPkgs - countPkgSized, countPkgUnsized);
87
88	return B_OK;
89}
90
91
92off_t
93PopulatePkgSizesProcess::_DeriveSize(const PackageInfoRef package) const
94{
95	BPath path;
96	if (PackageUtils::DeriveLocalFilePath(package.Get(), path) == B_OK) {
97		BEntry entry(path.Path());
98		struct stat s = {};
99		if (entry.GetStat(&s) == B_OK)
100			return s.st_size;
101		else
102			HDDEBUG("unable to get the size of local file [%s]", path.Path());
103	} else
104		HDDEBUG("unable to get the local file of package [%s]", package->Name().String());
105	return 0;
106}