MCPcopy Create free account
hub / github.com/FEX-Emu/FEX / RecoverGuestProgramFilename

Function RecoverGuestProgramFilename

Source/Common/Config.cpp:337–401  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

335}
336
337fextl::string RecoverGuestProgramFilename(fextl::string Program, bool ExecFDInterp, int ProgramFDFromEnv) {
338 // If executed with a FEX FD then the Program argument might be empty.
339 // In this case we need to scan the FD node to recover the application binary that exists on disk.
340 // Only do this if the Program argument is empty, since we would prefer the application's expectation
341 // of application name.
342 if (ProgramFDFromEnv != -1 && Program.empty()) {
343 // Get the `dev` node of the execveat fd string.
344 Program = fextl::fmt::format("/dev/fd/{}", ProgramFDFromEnv);
345 }
346
347 // If we were provided a relative path then we need to canonicalize it to become absolute.
348 // If the program name isn't resolved to an absolute path then glibc breaks inside it's `_dl_get_origin` function.
349 // This is because we rewrite `/proc/self/exe` to the absolute program path calculated in here.
350 if (!Program.starts_with('/')) {
351 char ExistsTempPath[PATH_MAX];
352 char* RealPath = FHU::Filesystem::Absolute(Program.c_str(), ExistsTempPath);
353 if (RealPath) {
354 Program = RealPath;
355 }
356 }
357
358 // If FEX was invoked through an FD path (either binfmt_misc or execveat) then we need to check the
359 // Program to see if it is a symlink to find the real path.
360 //
361 // binfmt_misc: Arg[0] is actually the execve `pathname` argument or `/dev/fd/<FD>` path
362 // - `pathname` with execve (See Side Note)
363 // - FD path with execveat and FD doesn't have an existing file on the disk
364 //
365 // ProgramFDFromEnv: Arg[0] is Application provided data or `/dev/fd/<FD>` from above fix-up.
366 // - execveat was either passed no arguments (argv=NULL) or the first argument is an empty string (argv[0]="").
367 // - FD path with execveat and FD doesn't have an existing file on the disk
368 //
369 // Side Note:
370 // The `execve` syscall doesn't take an FD but binfmt_misc will give FEX an FD to execute still.
371 // Arg[0] will always contain the `pathname` argument provided to execve.
372 // It does not resolve symlinks, and it does not convert the path to absolute.
373 //
374 // Examples:
375 // - Regular execve. Application must exist on disk.
376 // execve binfmt_misc args layout: `FEXInterpreter <Path provided to execve pathname> <user provided argv[0]> <user provided argv[n]>...`
377 // - Regular execveat with FD. FD is backed by application on disk.
378 // execveat binfmt_misc args layout: `FEXInterpreter <Path provided to execve pathname> <user provided argv[0]> <user provided argv[n]>...`
379 // - Regular execveat with FD. FD points to file on disk that has been deleted.
380 // execveat binfmt_misc args layout: `FEXInterpreter /dev/fd/<FD> <user provided argv[0]> <user provided argv[n]>...`
381#ifndef _WIN32
382 if (ExecFDInterp || ProgramFDFromEnv != -1) {
383 // Only in the case that FEX is executing an FD will the program argument potentially be a symlink.
384 // This symlink will be in the style of `/dev/fd/<FD>`.
385 //
386 // If the argument /is/ a symlink then resolve its path to get the original application name.
387 if (FHU::Symlinks::IsSymlink(Program)) {
388 char Filename[PATH_MAX];
389 auto SymlinkPath = FHU::Symlinks::ResolveSymlink(Program, Filename);
390 if (SymlinkPath.starts_with('/')) {
391 // This file was executed through an FD.
392 // Remove the ` (deleted)` text if the file was deleted after the fact.
393 // Otherwise just get the symlink without the deleted text.
394 return fextl::string {SymlinkPath.substr(0, SymlinkPath.rfind(" (deleted)"))};

Callers 1

GetApplicationNamesFunction · 0.85

Calls 4

formatFunction · 0.85
AbsoluteFunction · 0.85
ResolveSymlinkFunction · 0.85
IsSymlinkFunction · 0.50

Tested by

no test coverage detected