mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +02:00
Merge pull request #2237 from disarray2077/patch-8
linux: Implement `Process` methods and `Path.GetActualPathName`
This commit is contained in:
commit
2e9a2f3eb3
1 changed files with 257 additions and 7 deletions
|
@ -832,6 +832,17 @@ BFP_EXPORT void BFP_CALLTYPE BfpSystem_GetComputerName(char* outStr, int* inOutS
|
||||||
|
|
||||||
// BfpProcess
|
// BfpProcess
|
||||||
|
|
||||||
|
struct BfpProcess
|
||||||
|
{
|
||||||
|
pid_t mProcessId;
|
||||||
|
String mImageName;
|
||||||
|
|
||||||
|
BfpProcess()
|
||||||
|
{
|
||||||
|
mProcessId = -1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
BFP_EXPORT intptr BFP_CALLTYPE BfpProcess_GetCurrentId()
|
BFP_EXPORT intptr BFP_CALLTYPE BfpProcess_GetCurrentId()
|
||||||
{
|
{
|
||||||
return getpid();
|
return getpid();
|
||||||
|
@ -844,18 +855,87 @@ BFP_EXPORT bool BFP_CALLTYPE BfpProcess_IsRemoteMachine(const char* machineName)
|
||||||
|
|
||||||
BFP_EXPORT BfpProcess* BFP_CALLTYPE BfpProcess_GetById(const char* machineName, int processId, BfpProcessResult* outResult)
|
BFP_EXPORT BfpProcess* BFP_CALLTYPE BfpProcess_GetById(const char* machineName, int processId, BfpProcessResult* outResult)
|
||||||
{
|
{
|
||||||
|
#ifdef BF_PLATFORM_LINUX
|
||||||
|
pid_t pid = static_cast<pid_t>(processId);
|
||||||
|
|
||||||
|
char proc_dir[64];
|
||||||
|
snprintf(proc_dir, sizeof(proc_dir), "/proc/%d", pid);
|
||||||
|
|
||||||
|
if (access(proc_dir, F_OK) != 0)
|
||||||
|
{
|
||||||
|
OUTRESULT(BfpProcessResult_NotFound);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
BfpProcess* process = new BfpProcess();
|
||||||
|
process->mProcessId = pid;
|
||||||
|
return process;
|
||||||
|
#else
|
||||||
NOT_IMPL;
|
NOT_IMPL;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BFP_EXPORT void BFP_CALLTYPE BfpProcess_Enumerate(const char* machineName, BfpProcess** outProcesses, int* inOutProcessesSize, BfpProcessResult* outResult)
|
BFP_EXPORT void BFP_CALLTYPE BfpProcess_Enumerate(const char* machineName, BfpProcess** outProcesses, int* inOutProcessesSize, BfpProcessResult* outResult)
|
||||||
{
|
{
|
||||||
|
#ifdef BF_PLATFORM_LINUX
|
||||||
|
DIR* procDir = opendir("/proc");
|
||||||
|
if (!procDir)
|
||||||
|
{
|
||||||
|
*inOutProcessesSize = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Beefy::Array<BfpProcess*> processList;
|
||||||
|
struct dirent* entry;
|
||||||
|
while ((entry = readdir(procDir)) != NULL)
|
||||||
|
{
|
||||||
|
const char* name = entry->d_name;
|
||||||
|
bool is_pid = name[0] != '\0';
|
||||||
|
for (const char* p = name; *p; ++p)
|
||||||
|
{
|
||||||
|
if (*p < '0' || *p > '9')
|
||||||
|
{
|
||||||
|
is_pid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_pid)
|
||||||
|
{
|
||||||
|
pid_t pid = static_cast<pid_t>(atoi(name));
|
||||||
|
if (pid == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BfpProcess* proc = new BfpProcess();
|
||||||
|
proc->mProcessId = pid;
|
||||||
|
processList.Add(proc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(procDir);
|
||||||
|
|
||||||
|
if (static_cast<int>(processList.size()) > *inOutProcessesSize)
|
||||||
|
{
|
||||||
|
*inOutProcessesSize = static_cast<int>(processList.size());
|
||||||
|
OUTRESULT(BfpProcessResult_InsufficientBuffer);
|
||||||
|
for (BfpProcess* p_del : processList)
|
||||||
|
delete p_del;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < processList.size(); ++i)
|
||||||
|
outProcesses[i] = processList[i];
|
||||||
|
*inOutProcessesSize = static_cast<int>(processList.size());
|
||||||
|
OUTRESULT(BfpProcessResult_Ok);
|
||||||
|
#else
|
||||||
NOT_IMPL;
|
NOT_IMPL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BFP_EXPORT void BFP_CALLTYPE BfpProcess_Release(BfpProcess* process)
|
BFP_EXPORT void BFP_CALLTYPE BfpProcess_Release(BfpProcess* process)
|
||||||
{
|
{
|
||||||
NOT_IMPL;
|
delete process;
|
||||||
}
|
}
|
||||||
|
|
||||||
BFP_EXPORT bool BFP_CALLTYPE BfpProcess_WaitFor(BfpProcess* process, int waitMS, int* outExitCode, BfpProcessResult* outResult)
|
BFP_EXPORT bool BFP_CALLTYPE BfpProcess_WaitFor(BfpProcess* process, int waitMS, int* outExitCode, BfpProcessResult* outResult)
|
||||||
|
@ -865,18 +945,49 @@ BFP_EXPORT bool BFP_CALLTYPE BfpProcess_WaitFor(BfpProcess* process, int waitMS,
|
||||||
|
|
||||||
BFP_EXPORT void BFP_CALLTYPE BfpProcess_GetMainWindowTitle(BfpProcess* process, char* outTitle, int* inOutTitleSize, BfpProcessResult* outResult)
|
BFP_EXPORT void BFP_CALLTYPE BfpProcess_GetMainWindowTitle(BfpProcess* process, char* outTitle, int* inOutTitleSize, BfpProcessResult* outResult)
|
||||||
{
|
{
|
||||||
NOT_IMPL;
|
String title;
|
||||||
|
TryStringOut(title, outTitle, inOutTitleSize, (BfpResult*)outResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
BFP_EXPORT void BFP_CALLTYPE BfpProcess_GetProcessName(BfpProcess* process, char* outName, int* inOutNameSize, BfpProcessResult* outResult)
|
BFP_EXPORT void BFP_CALLTYPE BfpProcess_GetProcessName(BfpProcess* process, char* outName, int* inOutNameSize, BfpProcessResult* outResult)
|
||||||
{
|
{
|
||||||
|
if (process->mImageName.IsEmpty())
|
||||||
|
{
|
||||||
|
#ifdef BF_PLATFORM_LINUX
|
||||||
|
char path[PATH_MAX];
|
||||||
|
snprintf(path, sizeof(path), "/proc/%d/exe", process->mProcessId);
|
||||||
|
char name_buf[PATH_MAX] = {0};
|
||||||
|
ssize_t len = readlink(path, name_buf, sizeof(name_buf) - 1);
|
||||||
|
if (len != -1)
|
||||||
|
{
|
||||||
|
name_buf[len] = '\0';
|
||||||
|
process->mImageName.Append(basename(name_buf));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Only 15 characters of the process name are returned by this, but it works for all processes.
|
||||||
|
snprintf(path, sizeof(path), "/proc/%d/comm", process->mProcessId);
|
||||||
|
FILE* fp = fopen(path, "r");
|
||||||
|
if (fp)
|
||||||
|
{
|
||||||
|
if (fgets(name_buf, sizeof(name_buf), fp)) {
|
||||||
|
size_t len = strcspn(name_buf, "\n");
|
||||||
|
name_buf[len] = '\0';
|
||||||
|
process->mImageName.Append(name_buf, len);
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
NOT_IMPL;
|
NOT_IMPL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
TryStringOut(process->mImageName, outName, inOutNameSize, (BfpResult*)outResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
BFP_EXPORT int BFP_CALLTYPE BfpProcess_GetProcessId(BfpProcess* process)
|
BFP_EXPORT int BFP_CALLTYPE BfpProcess_GetProcessId(BfpProcess* process)
|
||||||
{
|
{
|
||||||
NOT_IMPL;
|
return process->mProcessId;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BfpSpawn
|
// BfpSpawn
|
||||||
|
@ -2392,9 +2503,148 @@ BFP_EXPORT void BFP_CALLTYPE BfpFile_GetFullPath(const char* inPath, char* outPa
|
||||||
TryStringOut(str, outPath, inOutPathSize, (BfpResult*)outResult);
|
TryStringOut(str, outPath, inOutPathSize, (BfpResult*)outResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
BFP_EXPORT void BFP_CALLTYPE BfpFile_GetActualPath(const char* inPath, char* outPath, int* inOutPathSize, BfpFileResult* outResult)
|
BFP_EXPORT void BFP_CALLTYPE BfpFile_GetActualPath(const char* inPathC, char* outPathC, int* inOutPathSize, BfpFileResult* outResult)
|
||||||
{
|
{
|
||||||
NOT_IMPL;
|
String inPath = inPathC;
|
||||||
|
String outPath;
|
||||||
|
|
||||||
|
// Check for '/../' backtracking - handle those first
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int32 lastComponentStart = -1;
|
||||||
|
|
||||||
|
while (i < inPath.mLength)
|
||||||
|
{
|
||||||
|
// Skip until path separator
|
||||||
|
while ((i < inPath.mLength) && (inPath[i] != DIR_SEP_CHAR) && (inPath[i] != DIR_SEP_CHAR_ALT))
|
||||||
|
++i;
|
||||||
|
|
||||||
|
if (lastComponentStart != -1)
|
||||||
|
{
|
||||||
|
if ((i - lastComponentStart == 2) && (inPath[lastComponentStart] == '.') && (inPath[lastComponentStart + 1] == '.'))
|
||||||
|
{
|
||||||
|
// Backtrack
|
||||||
|
while ((lastComponentStart > 0) &&
|
||||||
|
((inPath[lastComponentStart - 1] == DIR_SEP_CHAR) || (inPath[lastComponentStart - 1] == DIR_SEP_CHAR_ALT)))
|
||||||
|
lastComponentStart--;
|
||||||
|
while ((lastComponentStart > 0) && (inPath[lastComponentStart - 1] != DIR_SEP_CHAR) && (inPath[lastComponentStart - 1] != DIR_SEP_CHAR_ALT))
|
||||||
|
lastComponentStart--;
|
||||||
|
inPath.Remove(lastComponentStart, i - lastComponentStart + 1);
|
||||||
|
i = lastComponentStart;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if ((i - lastComponentStart == 1) && (inPath[lastComponentStart] == '.'))
|
||||||
|
{
|
||||||
|
inPath.Remove(lastComponentStart, i - lastComponentStart + 1);
|
||||||
|
i = lastComponentStart;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++i;
|
||||||
|
// Ignore multiple slashes in a row
|
||||||
|
while ((i < inPath.mLength) && ((inPath[i] == DIR_SEP_CHAR) || (inPath[i] == DIR_SEP_CHAR_ALT)))
|
||||||
|
++i;
|
||||||
|
|
||||||
|
lastComponentStart = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 i = 0;
|
||||||
|
int length = (int)inPath.length();
|
||||||
|
|
||||||
|
if (length >= 1)
|
||||||
|
{
|
||||||
|
// Handle root paths starting with '/' or '\'
|
||||||
|
if ((inPath[0] == DIR_SEP_CHAR) || (inPath[0] == DIR_SEP_CHAR_ALT))
|
||||||
|
{
|
||||||
|
i++; // start after initial slash
|
||||||
|
outPath.Append(DIR_SEP_CHAR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Relative path - prepend current working directory
|
||||||
|
char cwd[PATH_MAX];
|
||||||
|
if (getcwd(cwd, PATH_MAX) != NULL)
|
||||||
|
{
|
||||||
|
outPath.Append(cwd);
|
||||||
|
if (outPath[outPath.length() - 1] != DIR_SEP_CHAR)
|
||||||
|
outPath.Append(DIR_SEP_CHAR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 lastComponentStart = i;
|
||||||
|
bool addSeparator = false;
|
||||||
|
String subName;
|
||||||
|
|
||||||
|
while (i < length)
|
||||||
|
{
|
||||||
|
// skip until path separator
|
||||||
|
while ((i < length) && (inPath[i] != DIR_SEP_CHAR) && (inPath[i] != DIR_SEP_CHAR_ALT))
|
||||||
|
++i;
|
||||||
|
|
||||||
|
if (addSeparator)
|
||||||
|
outPath.Append(DIR_SEP_CHAR);
|
||||||
|
|
||||||
|
subName.Clear();
|
||||||
|
subName = inPath.Substring(0, i);
|
||||||
|
for (int j = 0; j < (int)subName.length(); j++)
|
||||||
|
if (subName[j] == DIR_SEP_CHAR_ALT)
|
||||||
|
subName[j] = DIR_SEP_CHAR;
|
||||||
|
|
||||||
|
String parentPath;
|
||||||
|
String componentName;
|
||||||
|
int32 lastSep = subName.LastIndexOf(DIR_SEP_CHAR);
|
||||||
|
|
||||||
|
if (lastSep != -1)
|
||||||
|
{
|
||||||
|
parentPath = subName.Substring(0, lastSep);
|
||||||
|
if (parentPath.length() == 0)
|
||||||
|
parentPath = "/";
|
||||||
|
componentName = subName.Substring(lastSep + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parentPath = ".";
|
||||||
|
componentName = subName;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
DIR* dir = opendir(parentPath.c_str());
|
||||||
|
if (dir != NULL)
|
||||||
|
{
|
||||||
|
struct dirent* entry = NULL;
|
||||||
|
while ((entry = readdir(dir)) != NULL)
|
||||||
|
{
|
||||||
|
// Linux is case-sensitive, but we do a case-insensitive comparison
|
||||||
|
// to help find the correct case for the file
|
||||||
|
if (strcasecmp(entry->d_name, componentName.c_str()) == 0)
|
||||||
|
{
|
||||||
|
outPath.Append(entry->d_name);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
// If not found, use the original component name
|
||||||
|
outPath.Append(inPath.Substring(lastComponentStart, i - lastComponentStart));
|
||||||
|
}
|
||||||
|
|
||||||
|
++i;
|
||||||
|
// Ignore multiple slashes in a row
|
||||||
|
while ((i < length) && ((inPath[i] == DIR_SEP_CHAR) || (inPath[i] == DIR_SEP_CHAR_ALT)))
|
||||||
|
++i;
|
||||||
|
|
||||||
|
lastComponentStart = i;
|
||||||
|
addSeparator = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TryStringOut(outPath, outPathC, inOutPathSize, (BfpResult*)outResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
// BfpFindFileData
|
// BfpFindFileData
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue