Files
pip/libs/main/system/pisysteminfo.cpp
peri4 a299ada873 PIFile::readAll release
patch deploy_tool: ignore libc.so and take last dpkg dependency instead of first
2025-09-05 21:46:44 +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];
piZeroMemory(in, 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];
piZeroMemory(in, 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";
piZeroMemory(in, 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);
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;
}