1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 03:28:20 +02:00

Merge pull request #2237 from disarray2077/patch-8

linux: Implement `Process` methods and `Path.GetActualPathName`
This commit is contained in:
Brian Fiete 2025-05-12 07:50:47 +02:00 committed by GitHub
commit 2e9a2f3eb3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -832,6 +832,17 @@ BFP_EXPORT void BFP_CALLTYPE BfpSystem_GetComputerName(char* outStr, int* inOutS
// BfpProcess
struct BfpProcess
{
pid_t mProcessId;
String mImageName;
BfpProcess()
{
mProcessId = -1;
}
};
BFP_EXPORT intptr BFP_CALLTYPE BfpProcess_GetCurrentId()
{
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)
{
#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;
return NULL;
#endif
}
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;
#endif
}
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)
@ -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)
{
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)
{
NOT_IMPL;
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;
#endif
}
TryStringOut(process->mImageName, outName, inOutNameSize, (BfpResult*)outResult);
}
BFP_EXPORT int BFP_CALLTYPE BfpProcess_GetProcessId(BfpProcess* process)
{
NOT_IMPL;
return 0;
return process->mProcessId;
}
// BfpSpawn
@ -2392,9 +2503,148 @@ BFP_EXPORT void BFP_CALLTYPE BfpFile_GetFullPath(const char* inPath, char* outPa
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