1049 lines
20 KiB
C++
1049 lines
20 KiB
C++
#include "utils.h"
|
|
|
|
#include "huagao/brand.h"
|
|
#include "ini_file.h"
|
|
|
|
|
|
#include <mutex>
|
|
#include <algorithm>
|
|
|
|
#if OS_WIN
|
|
#include <direct.h>
|
|
#include <Windows.h>
|
|
#include <time.h>
|
|
#include <Psapi.h>
|
|
#include <Tlhelp32.h>
|
|
#pragma comment(lib, "Psapi.lib")
|
|
|
|
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 // microseconds from '1601-01-01 00:00:00' to '1970-01-01 00:00:00'
|
|
|
|
int gettimeofday(TIMEV* tv, struct timezone* tz)
|
|
{
|
|
FILETIME ft = { 0 };
|
|
uint64_t ui64 = 0;
|
|
static bool set_tz = true;
|
|
|
|
GetSystemTimeAsFileTime(&ft); // 100 ns - from 1601-01-01 00:00:00
|
|
ui64 = ft.dwHighDateTime;
|
|
ui64 <<= 32;
|
|
ui64 |= ft.dwLowDateTime;
|
|
|
|
// convert to microseconds ...
|
|
ui64 += 5;
|
|
ui64 /= 10;
|
|
|
|
// move to 1970-01-01 00:00:00
|
|
ui64 -= DELTA_EPOCH_IN_MICROSECS;
|
|
if (tv)
|
|
{
|
|
tv->tv_sec = ui64 / 1000000;
|
|
tv->tv_usec = ui64 % 1000000;
|
|
}
|
|
|
|
if (tz)
|
|
{
|
|
if (set_tz)
|
|
{
|
|
set_tz = false;
|
|
_tzset();
|
|
}
|
|
tz->tz_minuteswest = _timezone / 60;
|
|
tz->tz_dsttime = _daylight;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#else
|
|
|
|
#include <map>
|
|
#include <sys/sysinfo.h>
|
|
#include <unistd.h>
|
|
#include <dirent.h>
|
|
#include <fcntl.h>
|
|
#include <sys/stat.h>
|
|
#include <thread>
|
|
#include <iconv.h>
|
|
#include <sys/vfs.h>
|
|
|
|
static std::mutex ini_lock_;
|
|
static std::map<std::string, simple_ini*> ini_files_;
|
|
static simple_ini* get_ini_object(const char* file)
|
|
{
|
|
std::lock_guard<std::mutex> lock(ini_lock_);
|
|
|
|
if (ini_files_.count(file) == 0)
|
|
{
|
|
simple_ini* ini = new simple_ini();
|
|
ini->load(file);
|
|
|
|
ini_files_[file] = ini;
|
|
}
|
|
|
|
return ini_files_[file];
|
|
}
|
|
|
|
DWORD GetPrivateProfileStringA(const char* lpAppName, const char* lpKeyName, const char* lpDefault, char* lpReturnedString, DWORD nSize, const char* lpFileName)
|
|
{
|
|
simple_ini* ini = get_ini_object(lpFileName);
|
|
std::string str(ini->get(lpAppName, lpKeyName, lpDefault));
|
|
|
|
if (nSize)
|
|
{
|
|
if (nSize < str.length())
|
|
{
|
|
memcpy(lpReturnedString, str.c_str(), nSize);
|
|
}
|
|
else
|
|
{
|
|
strcpy(lpReturnedString, str.c_str());
|
|
nSize = str.length();
|
|
}
|
|
}
|
|
|
|
return nSize;
|
|
}
|
|
|
|
BOOL WritePrivateProfileStringA(const char* lpAppName, const char* lpKeyName, const char* lpString, const char* lpFileName)
|
|
{
|
|
simple_ini* ini = get_ini_object(lpFileName);
|
|
|
|
ini->set(lpAppName, lpKeyName, lpString);
|
|
ini->save(lpFileName);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
DWORD GetLastError(void)
|
|
{
|
|
return errno;
|
|
}
|
|
DWORD GetPrivateProfileIntA(const char* app, const char* key, DWORD def, const char* file)
|
|
{
|
|
std::string val(get_ini_object(file)->get(app, key));
|
|
|
|
return val.empty() ? def : atoi(val.c_str());
|
|
}
|
|
DWORD GetPrivateProfileStringA(const char* app, const char* key, const char* init, char* buf, size_t len, const char* file)
|
|
{
|
|
std::string val(get_ini_object(file)->get(app, key));
|
|
|
|
if(val.empty())
|
|
{
|
|
if(init)
|
|
{
|
|
strcpy(buf, init);
|
|
len = strlen(init);
|
|
}
|
|
else
|
|
{
|
|
len = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(len < val.length())
|
|
memcpy(buf, val.c_str(), len);
|
|
else
|
|
{
|
|
strcpy(buf, val.c_str());
|
|
len = val.length();
|
|
}
|
|
}
|
|
|
|
return len;
|
|
}
|
|
void Sleep(DWORD milliseconds)
|
|
{
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
|
|
}
|
|
int GetModuleFileNameA(HMODULE module, char* buf, size_t len)
|
|
{
|
|
std::string name(""),
|
|
val(utils::get_module_full_path((char*)module));
|
|
|
|
val += PATH_SEPARATOR + name;
|
|
if(len < val.length())
|
|
memcpy(buf, val.c_str(), len);
|
|
else
|
|
{
|
|
strcpy(buf, val.c_str());
|
|
len = val.length();
|
|
}
|
|
|
|
return len;
|
|
}
|
|
int GetCurrentThreadId(void)
|
|
{
|
|
return pthread_self();
|
|
}
|
|
int GetCurrentProcessId(void)
|
|
{
|
|
return getpid();
|
|
}
|
|
|
|
#endif
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// log class
|
|
#define MAX_LOG_FILE_SIZE SIZE_MB(10)
|
|
|
|
class log_cls
|
|
{
|
|
void(*log_)(const char*, void*, void*);
|
|
std::string path_file_;
|
|
FILE* file_;
|
|
int level_;
|
|
int type_;
|
|
std::mutex lock_;
|
|
|
|
static log_cls* inst_;
|
|
|
|
static FILE* create_log_file(const char* path_file, bool truncate)
|
|
{
|
|
FILE* file_ = fopen(path_file, "a+b");
|
|
|
|
if (file_)
|
|
{
|
|
fseek(file_, 0, SEEK_END);
|
|
if (ftell(file_) == 0)
|
|
{
|
|
unsigned char bom[] = { 0x0ef, 0x0bb, 0x0bf };
|
|
fwrite(bom, sizeof(bom), 1, file_);
|
|
}
|
|
else
|
|
{
|
|
std::string sep("\n\n===================================================================================================================\n");
|
|
fwrite(sep.c_str(), sizeof(sep[0]), sep.length(), file_);
|
|
}
|
|
|
|
std::string now("[" + utils::format_current_time() + "]: =====================================");
|
|
now += truncate ? "--truncated--=====================================\n" : "--started--=====================================\n";
|
|
fwrite(now.c_str(), sizeof(now[0]), now.length(), file_);
|
|
}
|
|
|
|
return file_;
|
|
}
|
|
static void log_none(const char* info, void* param, void* param2)
|
|
{}
|
|
static void log_consonle(const char* info, void* param, void* param2)
|
|
{
|
|
printf(info);
|
|
}
|
|
static void log_file(const char* info, void* param, void* param2)
|
|
{
|
|
FILE** file = (FILE**)param;
|
|
|
|
if (*file == nullptr)
|
|
*file = create_log_file(((std::string*)param2)->c_str(), false);
|
|
|
|
if (*file)
|
|
{
|
|
fwrite(info, 1, strlen(info), *file);
|
|
fflush(*file);
|
|
if (ftell(*file) >= MAX_LOG_FILE_SIZE)
|
|
{
|
|
fclose(*file);
|
|
remove(((std::string*)param2)->c_str());
|
|
*file = create_log_file(((std::string*)param2)->c_str(), true);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
protected:
|
|
log_cls() : path_file_(""), file_(0), log_(&log_cls::log_consonle), level_(LOG_LEVEL_ALL)
|
|
{}
|
|
~log_cls()
|
|
{
|
|
if (file_)
|
|
{
|
|
fclose(file_);
|
|
file_ = 0;
|
|
}
|
|
}
|
|
|
|
public:
|
|
static log_cls* instance(void)
|
|
{
|
|
if (!log_cls::inst_)
|
|
log_cls::inst_ = new log_cls();
|
|
|
|
return log_cls::inst_;
|
|
}
|
|
static void clear(void)
|
|
{
|
|
if(log_cls::inst_)
|
|
{
|
|
delete log_cls::inst_;
|
|
log_cls::inst_ = nullptr;
|
|
}
|
|
}
|
|
|
|
int set_log_type(int type, void* param)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (file_)
|
|
{
|
|
fclose(file_);
|
|
file_ = 0;
|
|
}
|
|
|
|
type_ = type;
|
|
if (type == LOG_TYPE_NONE)
|
|
log_ = &log_cls::log_none;
|
|
else if (type == LOG_TYPE_CONSOLE)
|
|
log_ = &log_cls::log_consonle;
|
|
else if (type == LOG_TYPE_FILE)
|
|
{
|
|
log_ = &log_cls::log_file;
|
|
|
|
ret = -1;
|
|
if (param)
|
|
{
|
|
path_file_ = (char*)param;
|
|
file_ = create_log_file(path_file_.c_str(), false);
|
|
if (file_)
|
|
ret = 0;
|
|
}
|
|
}
|
|
|
|
if (ret != 0)
|
|
{
|
|
log_ = &log_cls::log_none;
|
|
type_ = LOG_TYPE_NONE;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
void set_log_level(int level)
|
|
{
|
|
level_ = level;
|
|
}
|
|
int level(void)
|
|
{
|
|
return level_;
|
|
}
|
|
int type(void)
|
|
{
|
|
return type_;
|
|
}
|
|
|
|
void log(const char* info)
|
|
{
|
|
std::lock_guard<std::mutex> lock(lock_);
|
|
|
|
log_(info, &file_, &path_file_);
|
|
}
|
|
std::string get_log_file_path(const char* dst = nullptr)
|
|
{
|
|
std::string file("");
|
|
|
|
if (log_ == &log_cls::log_file && file_)
|
|
{
|
|
file = path_file_;
|
|
|
|
if (dst)
|
|
{
|
|
file = dst;
|
|
|
|
FILE* dst = fopen(file.c_str(), "wb");
|
|
|
|
if (!dst)
|
|
file = "";
|
|
else
|
|
{
|
|
std::lock_guard<std::mutex> lock(lock_);
|
|
char buf[1024] = { 0 };
|
|
size_t l = 0;
|
|
|
|
fseek(file_, 0, SEEK_SET);
|
|
while ((l = fread(buf, 1, sizeof(buf), file_)))
|
|
fwrite(buf, 1, l, dst);
|
|
fclose(dst);
|
|
}
|
|
}
|
|
}
|
|
|
|
return file;
|
|
}
|
|
void clear_log(void)
|
|
{
|
|
if (log_ == &log_cls::log_file && file_)
|
|
{
|
|
std::lock_guard<std::mutex> lock(lock_);
|
|
|
|
fclose(file_);
|
|
remove(path_file_.c_str());
|
|
file_ = create_log_file(path_file_.c_str(), true);
|
|
}
|
|
}
|
|
};
|
|
log_cls* log_cls::inst_ = NULL;
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// util
|
|
|
|
namespace utils
|
|
{
|
|
static bool STDCALL match_part_filename(const char* path_name, bool dir, void* param)
|
|
{
|
|
std::string* partn = (std::string*)param;
|
|
|
|
if (!dir)
|
|
{
|
|
if (partn[0].empty())
|
|
{
|
|
partn[1] = path_name;
|
|
}
|
|
else
|
|
{
|
|
const char* name = strrchr(path_name, PATH_SEPARATOR[0]);
|
|
if (name++ == nullptr)
|
|
name = path_name;
|
|
|
|
std::string n(name);
|
|
to_lower(n);
|
|
if (strstr(n.c_str(), partn[0].c_str()))
|
|
partn[1] = path_name;
|
|
else
|
|
dir = true;
|
|
}
|
|
}
|
|
|
|
return dir;
|
|
}
|
|
|
|
#if OS_WIN
|
|
static std::string u2m(const wchar_t* u, int page)
|
|
{
|
|
char* ansi = NULL;
|
|
int len = 0;
|
|
std::string mb("");
|
|
|
|
len = WideCharToMultiByte(page, 0, u, lstrlenW(u), NULL, 0, NULL, NULL);
|
|
ansi = new char[len + 2];
|
|
len = WideCharToMultiByte(page, 0, u, lstrlenW(u), ansi, len, NULL, NULL);
|
|
ansi[len--] = 0;
|
|
mb = ansi;
|
|
delete[] ansi;
|
|
|
|
return mb;
|
|
}
|
|
static std::wstring m2u(const char* m, int page)
|
|
{
|
|
wchar_t* unic = NULL;
|
|
int len = 0;
|
|
std::wstring u(L"");
|
|
|
|
len = MultiByteToWideChar(page, 0, m, lstrlenA(m), NULL, 0);
|
|
unic = new wchar_t[len + 2];
|
|
len = MultiByteToWideChar(page, 0, m, lstrlenA(m), unic, len);
|
|
unic[len--] = 0;
|
|
u = unic;
|
|
delete[] unic;
|
|
|
|
return u;
|
|
}
|
|
|
|
std::string utf82ansi(const char* utf8)
|
|
{
|
|
return u2m(m2u(utf8, CP_UTF8).c_str(), CP_ACP);
|
|
}
|
|
std::string ansi2utf8(const char* ansi)
|
|
{
|
|
return u2m(m2u(ansi, CP_ACP).c_str(), CP_UTF8);
|
|
}
|
|
#else
|
|
// This function will return 'in' string if failed !
|
|
static std::string transform_between_gbk_and_utf8(const char* in, bool to_utf8, int *err)
|
|
{
|
|
size_t len = strlen(in) + 8, ol = len * 2;
|
|
char *buf = (char*)malloc(len), *oper = buf, *out = nullptr, *oper1 = nullptr;
|
|
iconv_t conv;
|
|
|
|
memset(buf, 0, len);
|
|
strcpy(buf, in);
|
|
if(to_utf8)
|
|
conv = iconv_open("UTF-8", "GBK");
|
|
else
|
|
conv = iconv_open("GBK", "UTF-8");
|
|
if(conv == (iconv_t)-1)
|
|
{
|
|
if(err)
|
|
*err = errno;
|
|
|
|
free(buf);
|
|
|
|
return in;
|
|
}
|
|
|
|
oper1 = out = (char*)malloc(ol);
|
|
memset(out, 0, ol);
|
|
len -= 8;
|
|
if(iconv(conv, &oper, &len, &oper1, &ol))
|
|
{
|
|
if(err)
|
|
*err = errno;
|
|
}
|
|
else if(err)
|
|
*err = 0;
|
|
|
|
std::string ret(out);
|
|
|
|
free(buf);
|
|
free(out);
|
|
iconv_close(conv);
|
|
|
|
return ret.empty() ? in : std::move(ret);
|
|
}
|
|
|
|
std::string utf82ansi(const char* utf8)
|
|
{
|
|
// fix me ...
|
|
return transform_between_gbk_and_utf8(utf8, false, nullptr);
|
|
}
|
|
std::string ansi2utf8(const char* ansi)
|
|
{
|
|
// fix me ...
|
|
return transform_between_gbk_and_utf8(ansi, true, nullptr);
|
|
}
|
|
#endif
|
|
|
|
std::string get_command_result(const char* cmd, int len)
|
|
{
|
|
std::string result("");
|
|
|
|
#if OS_WIN
|
|
#else
|
|
FILE* src = popen(cmd, "r");
|
|
|
|
if (src)
|
|
{
|
|
char buf[128] = { 0 };
|
|
int rv = fread(buf, 1, sizeof(buf) - 1, src);
|
|
|
|
while (rv > 0)
|
|
{
|
|
buf[rv] = 0;
|
|
result += buf;
|
|
if (len != -1 && result.length() >= len)
|
|
{
|
|
result.erase(len);
|
|
break;
|
|
}
|
|
rv = fread(buf, 1, sizeof(buf) - 1, src);
|
|
}
|
|
pclose(src);
|
|
}
|
|
#endif
|
|
|
|
return std::move(result);
|
|
}
|
|
std::string get_local_data_path(void)
|
|
{
|
|
static std::string ldp("");
|
|
|
|
if (ldp.empty())
|
|
{
|
|
#if OS_WIN
|
|
const char* path(getenv("LOCALAPPDATA"));
|
|
|
|
if (path)
|
|
{
|
|
ldp = path;
|
|
ldp += PATH_SEPARATOR;
|
|
}
|
|
#else
|
|
const char* path(getenv("HOME"));
|
|
|
|
if (path)
|
|
{
|
|
if (strstr(path, "/root"))
|
|
{
|
|
std::string usr(get_command_result("logname"));
|
|
ldp = std::string("/home/") + trim(usr);
|
|
if (!opendir(ldp.c_str()))
|
|
{
|
|
printf("opendir(%s) failed: %s\n", ldp.c_str(), strerror(errno));
|
|
ldp = path;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ldp = path;
|
|
}
|
|
ldp += std::string(PATH_SEPARATOR) + ".";
|
|
}
|
|
#endif
|
|
|
|
ldp += PRODUCT_VENDOR;
|
|
ldp += "Scan";
|
|
create_folder(ldp.c_str());
|
|
|
|
printf("# local data path: %s\n", ldp.c_str());
|
|
}
|
|
|
|
return ldp;
|
|
}
|
|
std::string temporary_path(void)
|
|
{
|
|
return std::move(simple_ini::temporary_path());
|
|
}
|
|
std::string format_current_time(void)
|
|
{
|
|
return std::move(chronograph::now());
|
|
}
|
|
std::string get_module_full_path(const char* part_name/*nullptr to get main-pe/first module's full path*/)
|
|
{
|
|
std::string file[] = { part_name ? part_name : "", ""};
|
|
|
|
to_lower(file[0]);
|
|
|
|
#if OS_WIN
|
|
if (part_name && *part_name)
|
|
{
|
|
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
|
|
MODULEENTRY32W pei = { 0 };
|
|
|
|
if (h != INVALID_HANDLE_VALUE)
|
|
{
|
|
pei.dwSize = sizeof(pei);
|
|
if (Module32FirstW(h, &pei))
|
|
{
|
|
do
|
|
{
|
|
char path[256] = { 0 };
|
|
|
|
GetModuleFileNameA(pei.hModule, path, _countof(path) - 1);
|
|
if (!match_part_filename(path, false, (void*)file))
|
|
break;
|
|
pei.dwSize = sizeof(pei);
|
|
} while (Module32NextW(h, &pei));
|
|
}
|
|
CloseHandle(h);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
char path[256] = { 0 };
|
|
|
|
GetModuleFileNameA(NULL, path, _countof(path) - 1);
|
|
file[1] = path;
|
|
}
|
|
#else
|
|
char path[128] = { 0 };
|
|
sprintf(path, "/proc/%u/map_files/", getpid());
|
|
enum_file(path, false, match_part_filename, (void*)file);
|
|
#endif
|
|
|
|
return std::move(file[1]);
|
|
}
|
|
std::string target_file_from_link(const char* lnk_file)
|
|
{
|
|
#if OS_WIN
|
|
std::string ret("");
|
|
|
|
return ret;
|
|
#else
|
|
char path[256] = { 0 };
|
|
int len = readlink(lnk_file, path, sizeof(path) - 1);
|
|
|
|
return len > 0 ? path : lnk_file;
|
|
#endif
|
|
}
|
|
std::string get_ini_value(const char* seg, const char* key, const char* cfg_file)
|
|
{
|
|
char buf[512] = { 0 };
|
|
|
|
GetPrivateProfileStringA(seg, key, "", buf, sizeof(buf) - 1, cfg_file);
|
|
|
|
return buf;
|
|
}
|
|
|
|
const char* to_lower(std::string& str)
|
|
{
|
|
std::transform(str.begin(), str.end(), str.begin(), tolower);
|
|
|
|
return str.c_str();
|
|
}
|
|
const char* trim(std::string& str, const char* sp)
|
|
{
|
|
int pos = 0;
|
|
char ch[2] = { 0 };
|
|
|
|
for (; pos < str.length(); ++pos)
|
|
{
|
|
ch[0] = str[pos];
|
|
if (!strstr(sp, ch))
|
|
break;
|
|
}
|
|
if (pos)
|
|
str.erase(0, pos);
|
|
|
|
pos = str.length() - 1;
|
|
for (; pos >= 0; --pos)
|
|
{
|
|
ch[0] = str[pos];
|
|
if (!strstr(sp, ch))
|
|
break;
|
|
}
|
|
if (++pos < str.length())
|
|
str.erase(pos);
|
|
|
|
return str.c_str();
|
|
}
|
|
|
|
bool create_folder(const char* folder)
|
|
{
|
|
int ret = MKDIR(folder, S_IREAD | S_IWRITE | S_IEXEC);
|
|
|
|
return ret == 0 || errno == EEXIST;
|
|
}
|
|
void set_ini_value(const char* seg, const char* key, const char* val, const char* cfg_file)
|
|
{
|
|
WritePrivateProfileStringA(seg, key, val, cfg_file);
|
|
}
|
|
int enum_file(const char* folder, bool recursive, bool(STDCALL* found)(const char* path_name, bool dir, void* param), void* param)
|
|
{
|
|
int ret = EACCES;
|
|
|
|
#if OS_WIN
|
|
WIN32_FIND_DATAA fd = { 0 };
|
|
HANDLE hf = FindFirstFileA(folder, &fd);
|
|
|
|
if (hf == INVALID_HANDLE_VALUE)
|
|
ret = GetLastError();
|
|
else
|
|
{
|
|
do
|
|
{
|
|
bool is_dir = (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY;
|
|
if (!found(fd.cFileName, is_dir, param))
|
|
{
|
|
ret = ERROR_CANCELLED;
|
|
break;
|
|
}
|
|
if (is_dir && recursive)
|
|
{
|
|
char* name = strrchr(fd.cFileName, PATH_SEPARATOR[0]);
|
|
if (name++ == NULL)
|
|
name = fd.cFileName;
|
|
if (strcmp(name, ".") && strcmp(name, ".."))
|
|
{
|
|
if (enum_file(fd.cFileName, recursive, found, param) == ERROR_CANCELLED)
|
|
{
|
|
ret = ERROR_CANCELLED;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} while (FindNextFileA(hf, &fd));
|
|
FindClose(hf);
|
|
}
|
|
#else
|
|
DIR* pdir = nullptr;
|
|
struct dirent* ent = nullptr;
|
|
|
|
pdir = opendir(folder);
|
|
if (!pdir)
|
|
ret = errno;
|
|
else
|
|
{
|
|
while ((ent = readdir(pdir)))
|
|
{
|
|
std::string file(folder);
|
|
|
|
file += PATH_SEPARATOR;
|
|
file += ent->d_name;
|
|
if (!found(target_file_from_link(file.c_str()).c_str(), ent->d_type & DT_DIR, param))
|
|
{
|
|
ret = ERROR_CANCELLED;
|
|
break;
|
|
}
|
|
|
|
if (ent->d_type & DT_DIR)
|
|
{
|
|
if (recursive)
|
|
{
|
|
if (strcmp(ent->d_name, ".") && strcmp(ent->d_name, ".."))
|
|
{
|
|
std::string sub(folder);
|
|
sub += PATH_SEPARATOR;
|
|
sub += ent->d_name;
|
|
if (enum_file(sub.c_str(), recursive, found, param) == ERROR_CANCELLED)
|
|
{
|
|
ret = ERROR_CANCELLED;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
int move_file(const char* from, const char* to)
|
|
{
|
|
return rename(from, to);
|
|
}
|
|
|
|
int get_disk_space(const char* path, unsigned long long* total, unsigned long long* avail, unsigned long long* block)
|
|
{
|
|
int ret = 0;
|
|
|
|
#if defined(WIN32) || defined(_WIN64)
|
|
ULARGE_INTEGER av = { 0 },
|
|
all = { 0 };
|
|
if (GetDiskFreeSpaceExA(path, &av, &all, NULL))
|
|
{
|
|
if (total)
|
|
*total = all.QuadPart;
|
|
if (avail)
|
|
*avail = av.QuadPart;
|
|
if (block)
|
|
{
|
|
DWORD sec = 0,
|
|
clu = 0;
|
|
std::string root(path);
|
|
size_t pos = root.find(":\\");
|
|
if (pos != std::string::npos)
|
|
root.erase(pos + 2);
|
|
if (GetDiskFreeSpaceA(root.c_str(), &clu, &sec, NULL, NULL))
|
|
{
|
|
*block = clu * sec;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
ret = GetLastError();
|
|
#else
|
|
struct statfs fs = { 0 };
|
|
|
|
ret = statfs(path, &fs);
|
|
if (ret == 0)
|
|
{
|
|
utils::to_log(LOG_LEVEL_DEBUG, " Total: %lld, Free: %lld, Avail: %lld, block size: %lld\n",
|
|
fs.f_blocks, fs.f_bfree, fs.f_bavail, fs.f_bsize);
|
|
if (total)
|
|
*total = fs.f_blocks * fs.f_bsize;
|
|
if (avail)
|
|
*avail = fs.f_bavail * fs.f_bsize;
|
|
if (block)
|
|
*block = fs.f_bsize;
|
|
}
|
|
#endif
|
|
return ret;
|
|
}
|
|
unsigned int get_page_size(unsigned int* map_unit)
|
|
{
|
|
unsigned int ps = 1024;
|
|
#if defined(WIN32) || defined(_WIN64)
|
|
SYSTEM_INFO si = { 0 };
|
|
|
|
GetSystemInfo(&si);
|
|
ps = si.dwPageSize;
|
|
if (map_unit)
|
|
*map_unit = si.dwAllocationGranularity;
|
|
#else
|
|
ps = sysconf(_SC_PAGESIZE);
|
|
if(ps < 1024 || (ps & 0x0fe0000ff)) // nKB && < 16MB
|
|
ps = getpagesize();
|
|
if (map_unit)
|
|
*map_unit = ps;
|
|
#endif
|
|
if (ps < 1024 || (ps & 0x0fe0000ff)) // nKB && < 16MB
|
|
ps = 1024;
|
|
|
|
return ps;
|
|
}
|
|
|
|
void init_log(log_type type, log_level level, const char* fn_appendix)
|
|
{
|
|
std::string file("");
|
|
|
|
if (type == LOG_TYPE_FILE)
|
|
{
|
|
file = get_local_data_path() + PATH_SEPARATOR + "Log";
|
|
create_folder(file.c_str());
|
|
|
|
std::string pe(get_module_full_path());
|
|
size_t pos = pe.rfind(PATH_SEPARATOR[0]);
|
|
|
|
if (pos++ == std::string::npos)
|
|
pos = 0;
|
|
file += PATH_SEPARATOR + pe.substr(pos);
|
|
if (fn_appendix)
|
|
file += fn_appendix;
|
|
file += ".log";
|
|
}
|
|
|
|
log_cls::instance()->set_log_type(type, &file[0]);
|
|
log_cls::instance()->set_log_level(level);
|
|
}
|
|
void uninit(void)
|
|
{
|
|
log_cls::clear();
|
|
}
|
|
void log_info(const char* info, int level)
|
|
{
|
|
if (get_log_type() != LOG_TYPE_NONE && get_log_level() <= level)
|
|
{
|
|
log_cls::instance()->log(("[" + format_current_time() + "]: " + info).c_str());
|
|
}
|
|
}
|
|
void log_mem_info(const char* desc, const void* data, size_t bytes, int level)
|
|
{
|
|
if (get_log_type() == LOG_TYPE_NONE || get_log_level() > level)
|
|
return;
|
|
|
|
std::string line(desc);
|
|
char buf[40] = {0};
|
|
|
|
utils::log_info((line + "\n").c_str(), level);
|
|
line = "";
|
|
for(size_t i = 0; i < bytes; ++i)
|
|
{
|
|
if((i % 16) == 0)
|
|
{
|
|
if(line.length())
|
|
utils::log_info((line + "\n").c_str(), level);
|
|
sprintf(buf, "%p ", (const char*)data + i);
|
|
line = buf;
|
|
}
|
|
else if((i % 8) == 0)
|
|
line += " ";
|
|
sprintf(buf, "%02x ", ((const unsigned char*)data)[i]);
|
|
line += buf;
|
|
}
|
|
if(line.length())
|
|
utils::log_info((line + "\n").c_str(), level);
|
|
}
|
|
int get_log_type(void)
|
|
{
|
|
return log_cls::instance()->type();
|
|
}
|
|
int get_log_level(void)
|
|
{
|
|
return log_cls::instance()->level();
|
|
}
|
|
|
|
int copy_log_file_to(const char* dst)
|
|
{
|
|
log_cls::instance()->get_log_file_path(dst);
|
|
|
|
return 0;
|
|
}
|
|
int clear_log_file(void)
|
|
{
|
|
log_cls::instance()->clear_log();
|
|
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// util
|
|
chronograph::chronograph()
|
|
{
|
|
reset();
|
|
}
|
|
chronograph::~chronograph()
|
|
{}
|
|
|
|
bool chronograph::now(TIMEV* tv)
|
|
{
|
|
struct timezone tz = { 0 };
|
|
|
|
return gettimeofday(tv, &tz) == 0;
|
|
}
|
|
bool chronograph::now(uint64_t* seconds, uint64_t* u_seconds)
|
|
{
|
|
TIMEV tv = { 0 };
|
|
struct timezone tz = { 0 };
|
|
|
|
if (gettimeofday(&tv, &tz) == 0)
|
|
{
|
|
if (seconds)
|
|
*seconds = tv.tv_sec;
|
|
if (u_seconds)
|
|
*u_seconds = tv.tv_usec;
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
std::string chronograph::now(bool with_ms/*whether with milliseconds*/) // return '2022-11-30 10:38:42.123', no '.123' if with_ms was false
|
|
{
|
|
TIMEV tv = { 0 };
|
|
|
|
if (!chronograph::now(&tv))
|
|
return "";
|
|
|
|
char buf[40] = { 0 };
|
|
time_t t = tv.tv_sec;
|
|
struct tm* l = localtime(&t);
|
|
|
|
if (with_ms)
|
|
sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d.%06d", l->tm_year + 1900, l->tm_mon + 1, l->tm_mday
|
|
, l->tm_hour, l->tm_min, l->tm_sec, tv.tv_usec);
|
|
else
|
|
sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d", l->tm_year + 1900, l->tm_mon + 1, l->tm_mday
|
|
, l->tm_hour, l->tm_min, l->tm_sec);
|
|
|
|
return buf;
|
|
}
|
|
|
|
uint64_t chronograph::elapse_s(void)
|
|
{
|
|
TIMEV tv = { 0 };
|
|
|
|
chronograph::now(&tv);
|
|
|
|
return tv.tv_sec - bgn_.tv_sec;
|
|
}
|
|
uint64_t chronograph::elapse_ms(void)
|
|
{
|
|
TIMEV tv = { 0 };
|
|
uint64_t dif = 0;
|
|
|
|
chronograph::now(&tv);
|
|
dif = SEC_2_MS(tv.tv_sec - bgn_.tv_sec);
|
|
dif += tv.tv_usec / MSEC_2_US(1);
|
|
dif -= bgn_.tv_usec / MSEC_2_US(1);
|
|
|
|
return dif;
|
|
}
|
|
uint64_t chronograph::elapse_us(void)
|
|
{
|
|
TIMEV tv = { 0 };
|
|
uint64_t dif = 0;
|
|
|
|
chronograph::now(&tv);
|
|
dif = SEC_2_US(tv.tv_sec - bgn_.tv_sec);
|
|
dif += tv.tv_usec;
|
|
dif -= bgn_.tv_usec;
|
|
|
|
return dif;
|
|
}
|
|
void chronograph::reset()
|
|
{
|
|
chronograph::now(&bgn_);
|
|
}
|
|
|
|
|
|
|
|
|