如何实现readlink来查找路径

时间:2011-04-02 20:29:30

标签: c++ linux path executable

使用readlink函数作为How do I find the location of the executable in C?的解决方案,我如何获取char数组的路径?此外,变量buf和bufsize代表什么,我如何初始化它们?

编辑:我正在尝试获取当前正在运行的程序的路径,就像上面链接的问题一样。该问题的答案是使用readlink("proc/self/exe")。我不知道如何在我的程序中实现它。我试过了:

char buf[1024];  
string var = readlink("/proc/self/exe", buf, bufsize);  

这显然是不正确的。

5 个答案:

答案 0 :(得分:37)

Use the readlink() function properly用于正确使用readlink功能。

如果您的路径位于std::string,则可以执行以下操作:

#include <unistd.h>
#include <limits.h>

std::string do_readlink(std::string const& path) {
    char buff[PATH_MAX];
    ssize_t len = ::readlink(path.c_str(), buff, sizeof(buff)-1);
    if (len != -1) {
      buff[len] = '\0';
      return std::string(buff);
    }
    /* handle error condition */
}

如果您只是在固定路径之后:

std::string get_selfpath() {
    char buff[PATH_MAX];
    ssize_t len = ::readlink("/proc/self/exe", buff, sizeof(buff)-1);
    if (len != -1) {
      buff[len] = '\0';
      return std::string(buff);
    }
    /* handle error condition */
}

使用它:

int main()
{
  std::string selfpath = get_selfpath();
  std::cout << selfpath << std::endl;
  return 0;
}

答案 1 :(得分:4)

让我们看看the manpage说的是什么:

 readlink() places the contents of the symbolic link path in the buffer
 buf, which has size bufsiz.  readlink does not append a NUL character to
 buf.

行。应该够简单。给出1024个字符的缓冲区:

 char buf[1024];

 /* The manpage says it won't null terminate.  Let's zero the buffer. */
 memset(buf, 0, sizeof(buf));

 /* Note we use sizeof(buf)-1 since we may need an extra char for NUL. */
 if (readlink("/proc/self/exe", buf, sizeof(buf)-1) < 0)
 {
    /* There was an error...  Perhaps the path does not exist
     * or the buffer is not big enough.  errno has the details. */
    perror("readlink");
    return -1;
 }

答案 2 :(得分:2)

接受的答案几乎是正确的,除非您不能依赖PATH_MAX,因为它是

  如果系统没有这样的话,

不保证按POSIX定义   限制。

(来自readlink(2)手册页)

此外,当它被定义时,它并不总是代表&#34; true&#34;限制。 (见http://insanecoding.blogspot.fr/2007/11/pathmax-simply-isnt.html

readlink的联机帮助页也提供了一种在符号链接上执行此操作的方法:

  

使用静态大小的缓冲区可能无法提供足够的空间          符号链接内容。缓冲区所需的大小可以是          从对lstat(2)的调用返回的stat.st_size值中获取          链接。但是,readlink()和read-写入的字节数          应检查linkat()以确保符号的大小          电话之间的链接没有增加。

但是对于大多数/ proc文件,在/ proc / self / exe /的情况下,stat.st_size将为0.我看到的唯一剩下的解决方案是调整缓冲区,但它不适合。< / p>

我建议将vector<char>用于此目的:

std::string get_selfpath()
{
    std::vector<char> buf(400);
    ssize_t len;

    do
    {
        buf.resize(buf.size() + 100);
        len = ::readlink("/proc/self/exe", &(buf[0]), buf.size());
    } while (buf.size() == len);

    if (len > 0)
    {
        buf[len] = '\0';
        return (std::string(&(buf[0])));
    }
    /* handle error */
    return "";
}

答案 3 :(得分:1)

char *
readlink_malloc (const char *filename)
{
  int size = 100;
  char *buffer = NULL;

  while (1)
    {
      buffer = (char *) xrealloc (buffer, size);
      int nchars = readlink (filename, buffer, size);
      if (nchars < 0)
        {
          free (buffer);
          return NULL;
        }
      if (nchars < size)
        return buffer;
      size *= 2;
    }
}

取自:http://www.delorie.com/gnu/docs/glibc/libc_279.html

答案 4 :(得分:1)

#include <stdlib.h>
#include <unistd.h>

static char *exename(void)
{
    char *buf;
    char *newbuf;
    size_t cap;
    ssize_t len;

    buf = NULL;
    for (cap = 64; cap <= 16384; cap *= 2) {
        newbuf = realloc(buf, cap);
        if (newbuf == NULL) {
            break;
        }
        buf = newbuf;
        len = readlink("/proc/self/exe", buf, cap);
        if (len < 0) {
            break;
        }
        if ((size_t)len < cap) {
            buf[len] = 0;
            return buf;
        }
    }
    free(buf);
    return NULL;
}

#include <stdio.h>

int main(void)
{
    char *e = exename();
    printf("%s\n", e ? e : "unknown");
    free(e);
    return 0;
}

这使用传统的“当您不知道正确的缓冲区大小时,重新分配增加的2的幂”技巧。我们假设为路径名分配少于64个字节是不值得的。我们还假设长达16384(2 ** 14)个字节的可执行文件路径名必须指示程序安装方式中的某种异常,并且知道路径名没有用,因为我们很快就会遇到更大的问题要担心关于。

无需费心像PATH_MAX这样的常量。对于几乎所有路径名而言,保留这么多的内存都是过大的,并且如另一个答案中所述,无论如何,它不能保证是实际的上限。对于此应用程序,我们可以选择一个常识上限,例如16384。即使对于没有常识上限的应用程序,重新分配递增的2的幂也是一种不错的方法。您只需要log n个调用就可以得到一个n字节的结果,而您浪费的内存容量与结果的长度成正比。它还避免了竞争情况,在这种情况下,字符串的长度在realloc()readlink()之间变化。