当前执行程序的绝对路径

当前执行程序的绝对路径

argv[0]引用导致当前进程加载的 shell 命令。getcwd()返回当前工作目录。根据该信息,我可以构造程序的二进制可执行文件的绝对路径吗?如果程序cd自首次加载以来已经完成了 a,我不希望它起作用。

答案1

在编程语言解释器的内部,我使用以下代码来获取自身路径。

它有针对 Linux、Windows(包括 Cygwin)、Mac 和 Solaris 的特殊代码:

#if __APPLE__
#include <mach-o/dyld.h>
#endif

#if __linux__
static val get_self_path(void)
{
  char self[PATH_MAX] = { 0 };
  int nchar = readlink("/proc/self/exe", self, sizeof self);

  if (nchar < 0 || nchar >= convert(int, sizeof self))         
    return nil;
  return string_utf8(self);
}
#elif HAVE_WINDOWS_H
static val get_self_path(void)
{
  wchar_t self[MAX_PATH] = { 0 };
  DWORD nchar;

  SetLastError(0);
  nchar = GetModuleFileNameW(NULL, self, MAX_PATH);

  if (nchar == 0 ||
      (nchar == MAX_PATH &&
       ((GetLastError() == ERROR_INSUFFICIENT_BUFFER) ||
        (self[MAX_PATH - 1] != 0))))
    return nil;

  return string(self);
}
#elif __APPLE__
static val get_self_path(void)
{
  char self[PATH_MAX] = { 0 };
  uint32_t size = sizeof self;

  if (_NSGetExecutablePath(self, &size) != 0)
    return nil;
  return string_utf8(self);
}
#elif HAVE_GETEXECNAME
static val get_self_path(void)
{
  val execname = string_utf8(getexecname());
  if (car(execname) == chr('/'))
    return execname;
  return scat3(getcwd_wrap(), chr('/'), execname);
}
#else
static val get_self_path(void)
{
  char self[PATH_MAX];

  if (argv[0] && realpath(argv[0], self))
    return string_utf8(self);

   return lit(HARD_INSTALLATION_PATH);
}
#endif

类型val、符号和nil函数是解释器内部的。只是一个抽象铸造的宏。当然,还需要一些头文件,等等。stringstring_utf8convertreadlinkrealpath

getexecname函数是 Solaris 上的东西。似乎出于某种原因,我在处理相对路径的情况下进行了编码,在这种情况下,必须将当前目录粘贴到其上才能获得绝对路径。

后备策略是,如果argv[0]frommain可用,则调用realpath它并运行它。如果argv[0]不可用,那么我们依赖于来自变量的硬编码安装路径Makefile。例如,如果程序安装为/usr/bin/foo,则Makefile配方会将其作为 插入到编译器命令行中-DHARD_INSTALLATION_PATH=/usr/bin/foo。当然,只有当程序安装在其构建路径时,这才是正确的。

答案2

在 Linux 上,您可以使用符号链接/proc/self/exe

$ ls -l  /proc/self/exe
lrwxrwxrwx 1 rudi users 0 2016-10-18 16:20 /proc/self/exe -> /usr/bin/ls

相关内容