266 lines
6.2 KiB
C++
266 lines
6.2 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 "piincludes_p.h"
|
|
#include "pidir.h"
|
|
#include "picrc.h"
|
|
|
|
#ifdef ESP_PLATFORM
|
|
# include "esp_system.h"
|
|
# include "esp_spi_flash.h"
|
|
#endif
|
|
|
|
#define SALT_SIZE 8
|
|
|
|
|
|
PISystemInfo::MountInfo::MountInfo() {
|
|
space_all = space_used = space_free = 0;
|
|
removable = false;
|
|
}
|
|
|
|
|
|
|
|
|
|
PISystemInfo::PISystemInfo() {
|
|
processorsCount = 1;
|
|
}
|
|
|
|
|
|
PISystemInfo * PISystemInfo::instance() {
|
|
static PISystemInfo ret;
|
|
return &ret;
|
|
}
|
|
|
|
|
|
|
|
PIStringList PISystemInfo::mountRoots() {
|
|
PIStringList ret;
|
|
#ifdef WINDOWS
|
|
char letters[1024];
|
|
DWORD ll = GetLogicalDriveStrings(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 = GetLogicalDriveStrings(1023, letters);
|
|
PIString clet;
|
|
for (DWORD i = 0; i < ll; ++i) {
|
|
if (letters[i] == '\0') {
|
|
if (GetVolumeInformation(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 (GetDiskFreeSpace(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 (GetDriveType(clet.dataAscii()) == DRIVE_REMOVABLE)
|
|
m.removable = true;
|
|
clet.cutRight(1);
|
|
int qdd = QueryDosDevice(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();
|
|
piForeachC (PIString & 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)) {
|
|
PIFile f(conf, PIIODevice::ReadOnly);
|
|
f.open();
|
|
salt = f.readAll();
|
|
}
|
|
if (salt.size_s() != SALT_SIZE){
|
|
salt = generateSalt();
|
|
PIFile f(conf, PIIODevice::ReadWrite);
|
|
f.open();
|
|
f.clear();
|
|
f.write(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;
|
|
}
|