Files
pip/libs/main/system/pisysteminfo.cpp
peri4 caa7880cc4 get rid of piForeach
apply some code analyzer recommendations
ICU flag now check if libicu exists
prepare for more accurate growth of containers (limited PoT, then constantly increase size)
2024-11-20 20:01:47 +03:00

257 lines
6.1 KiB
C++

/*
PIP - Platform Independent Primitives
System information
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pisysteminfo.h"
#include "picrc.h"
#include "pidir.h"
#include "piincludes_p.h"
#ifdef ESP_PLATFORM
# include "esp_spi_flash.h"
# include "esp_system.h"
#endif
#define SALT_SIZE 8
PISystemInfo * PISystemInfo::instance() {
static PISystemInfo ret;
return &ret;
}
PIStringList PISystemInfo::mountRoots() {
PIStringList ret;
#ifdef WINDOWS
char letters[1024];
DWORD ll = GetLogicalDriveStringsA(1023, letters);
PIString clet;
for (uint i = 0; i < ll; ++i) {
if (letters[i] == '\0') {
if (clet.size_s() > 2) ret << clet.cutRight(1);
clet.clear();
} else
clet += PIChar(letters[i]);
}
#else
# ifdef LINUX
PIString s_df, s_m;
char in[1024];
memset(in, 0, 1024);
FILE * fp = popen("mount -l", "r");
PIStringList tl;
if (fp) {
while (fgets(in, 1024, fp)) {
tl = PIString(in).trim().replaceAll(" ", " ").split(" ");
if (tl.size_s() < 2) continue;
for (int i = 0; i < tl.size_s() - 1; ++i)
if (tl[i] == "on") {
if (!ret.contains(tl[i + 1])) ret << tl[i + 1];
break;
}
}
pclose(fp);
}
# else
# endif
#endif
return ret;
}
struct String3 {
PIString mp, type, label;
};
PIVector<PISystemInfo::MountInfo> PISystemInfo::mountInfo(bool ignore_cache) {
static PIVector<PISystemInfo::MountInfo> cache;
static PITimeMeasurer tm;
static bool first = true;
if (!ignore_cache) {
if (tm.elapsed_m() < piMountInfoRefreshIntervalMs && !first) return cache;
}
first = false;
tm.reset();
cache.clear();
PIVector<PISystemInfo::MountInfo> ret;
MountInfo m;
#ifdef WINDOWS
char letters[1024], volname[1024], volfs[1024];
DWORD ll = GetLogicalDriveStringsA(1023, letters);
PIString clet;
for (DWORD i = 0; i < ll; ++i) {
if (letters[i] == '\0') {
if (GetVolumeInformationA(clet.data(), volname, 1023, 0, 0, 0, volfs, 1023)) {
m.mount_point = clet;
m.filesystem = volfs;
m.label = volname;
DWORD spc, bps, free_cl, all_cl;
if (GetDiskFreeSpaceA(clet.data(), &spc, &bps, &free_cl, &all_cl)) {
ullong bpc = ullong(spc) * ullong(bps);
m.space_all = bpc * ullong(all_cl);
m.space_free = bpc * ullong(free_cl);
m.space_used = m.space_all - m.space_free;
} else
m.space_all = m.space_free = m.space_used = 0U;
if (GetDriveTypeA(clet.dataAscii()) == DRIVE_REMOVABLE) m.removable = true;
clet.cutRight(1);
int qdd = QueryDosDeviceA(clet.data(), volfs, 1023);
if (qdd > 0)
m.device = volfs;
else
m.device.clear();
ret << m;
}
clet.clear();
} else
clet += PIChar(letters[i]);
}
#endif
#ifdef LINUX
PIString s_df, s_m;
char in[1024];
memset(in, 0, 1024);
// piCout << "mountInfo 0";
FILE * fp = popen("df -B1", "r");
PIStringList l_df;
PIMap<PIString, String3> fs;
if (fp) {
while (fgets(in, 1024, fp))
l_df << PIString(in).trim();
pclose(fp);
fp = 0;
}
// piCout << "mountInfo 1";
memset(in, 0, 1024);
fp = popen("mount -l", "r");
PIStringList tl;
if (fp) {
while (fgets(in, 1024, fp)) {
tl = PIString(in).trim().replaceAll(" ", " ").split(" ");
if (tl.size_s() < 2) continue;
String3 me;
PIString dev;
dev = tl.front();
for (int i = 0; i < tl.size_s() - 1; ++i) {
if (tl[i] == "on") {
me.mp = tl[i + 1];
++i;
continue;
}
if (tl[i] == "type") {
me.type = tl[i + 1];
++i;
continue;
}
}
if (tl.back().startsWith("[")) {
me.label = tl.back();
me.label.cutLeft(1).cutRight(1);
}
fs[dev] = me;
// piCout << fsmp << fstl;
}
pclose(fp);
fp = 0;
}
if (l_df.size_s() < 2) return ret;
l_df.pop_front();
for (const auto & s: l_df) {
PIStringList ml(s.replacedAll(" ", " ").split(" "));
if (ml.size_s() < 2) continue;
if (ml.front() == "none") continue;
m.space_all = ml[1].toULLong();
m.space_used = ml[2].toULLong();
m.space_free = m.space_all - m.space_used;
String3 s3 = fs.value(ml.front());
m.device = ml.front();
m.filesystem = s3.type;
m.mount_point = s3.mp;
m.label = s3.label;
ret << m;
// piCout << ml;
}
#endif
#ifdef ESP_PLATFORM
esp_chip_info_t chip_info;
esp_chip_info(&chip_info);
m.device = ((chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded SPI flash" : "external SPI flash");
m.space_all = spi_flash_get_chip_size();
m.mount_point = "/";
ret << m;
#endif
cache = ret;
return ret;
}
PIString confDir() {
return
#ifdef WINDOWS
PIDir::home().path() + "/AppData/Local"
#elif defined(ANDROID)
""
#else
PIDir::home().path() + "/.config"
#endif
;
}
PIByteArray generateSalt() {
PIByteArray ret;
piForTimes(SALT_SIZE) {
piMSleep(randomi() % 10);
randomize();
ret << uchar(randomi() % 0x100);
}
return ret;
}
PIString PISystemInfo::machineKey() {
static PIString ret;
if (ret.isEmpty()) {
PISystemInfo * si = instance();
PIByteArray salt;
PIString conf = confDir() + "/.pip_machine_salt";
if (PIFile::isExists(conf)) salt = PIFile::readAll(conf, false);
if (salt.size_s() != SALT_SIZE) {
salt = generateSalt();
PIFile::writeAll(conf, salt);
}
ret = si->OS_name + "_" + si->architecture + "_" + si->hostname + "_" + salt.toHex();
}
return ret;
}
uint PISystemInfo::machineID() {
static uint ret = 0;
if (ret == 0) {
CRC_32 crc = standardCRC_32();
ret = crc.calculate(machineKey().toByteArray());
// piCout << "machineID \"" << machineKey() << "\" =" << PICoutManipulators::Hex << ret;
}
return ret;
}