/* 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 . */ #include "pisysteminfo.h" #include "piincludes_p.h" #include "pidir.h" #include "picrc.h" #ifdef ESP_PLATFORM # include "esp_system.h" # include "esp_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(bool ignore_cache) { static PIVector 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 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 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 = esp_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; }