如何实现readlink查找路径

发布于 2024-10-29 01:29:57 字数 421 浏览 2 评论 0原文

使用 readlink 函数作为 的解决方案找到 C 中可执行文件的位置?,如何将路径获取到 char 数组中?另外,变量 buf 和 bufsize 代表什么以及如何初始化它们?

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

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

这显然是不正确的。

Using the readlink function used as a solution to How do I find the location of the executable in C?, how would I get the path into a char array? Also, what do the variables buf and bufsize represent and how do I initialize them?

EDIT: I am trying to get the path of the currently running program, just like the question linked above. The answer to that question said to use readlink("proc/self/exe"). I do not know how to implement that into my program. I tried:

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

This is obviously incorrect.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

习惯成性 2024-11-05 01:29:57

使用 readlink () 正常运行,以便正确使用 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;
}

This Use the readlink() function properly for the correct uses of the readlink function.

If you have your path in a std::string, you could do something like this:

#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 */
}

If you're only after a fixed path:

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 */
}

To use it:

int main()
{
  std::string selfpath = get_selfpath();
  std::cout << selfpath << std::endl;
  return 0;
}
上课铃就是安魂曲 2024-11-05 01:29:57

接受的答案几乎是正确的,但你不能依赖 PATH_MAX 因为它是

如果系统没有这样的定义,则不保证按照 POSIX 进行定义
限制。

(来自 readlink(2) 联机帮助页)

此外,当它被定义时,它并不总是代表“真实”限制。 (参见http://insanecoding.blogspot.fr/2007/11/pathmax -simply-isnt.html )

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

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

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

为此,我建议使用 vector ,如下所示:

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 "";
}

Accepted answer is almost correct, except you can't rely on PATH_MAX because it is

not guaranteed to be defined per POSIX if the system does not have such
limit.

(From readlink(2) manpage)

Also, when it's defined it doesn't always represent the "true" limit. (See http://insanecoding.blogspot.fr/2007/11/pathmax-simply-isnt.html )

The readlink's manpage also give a way to do that on symlink :

Using a statically sized buffer might not provide enough room for the
symbolic link contents. The required size for the buffer can be
obtained from the stat.st_size value returned by a call to lstat(2) on
the link. However, the number of bytes written by readlink() and read‐
linkat() should be checked to make sure that the size of the symbolic
link did not increase between the calls.

However in the case of /proc/self/exe/ as for most of /proc files, stat.st_size would be 0. The only remaining solution I see is to resize buffer while it doesn't fit.

I suggest the use of vector<char> as follow for this purpose:

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 "";
}
阳光下的泡沫是彩色的 2024-11-05 01:29:57

我们来看看手册页 说:

 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;
 }

Let's look at what the manpage says:

 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.

OK. Should be simple enough. Given your buffer of 1024 chars:

 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;
 }
情独悲 2024-11-05 01:29:57
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

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;
    }
}

Taken from: http://www.delorie.com/gnu/docs/glibc/libc_279.html

尽揽少女心 2024-11-05 01:29:57
#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() 之间变化的竞争条件。

#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;
}

This uses the traditional "when you don't know the right buffer size, reallocate increasing powers of two" trick. We assume that allocating less than 64 bytes for a pathname is not worth the effort. We also assume that an executable pathname as long as 16384 (2**14) bytes has to indicate some kind of anomaly in how the program was installed, and it's not useful to know the pathname as we'll soon encounter bigger problems to worry about.

There is no need to bother with constants like PATH_MAX. Reserving so much memory is overkill for almost all pathnames, and as noted in another answer, it's not guaranteed to be the actual upper limit anyway. For this application, we can pick a common-sense upper limit such as 16384. Even for applications with no common-sense upper limit, reallocating increasing powers of two is a good approach. You only need log n calls for a n-byte result, and the amount of memory capacity you waste is proportional to the length of the result. It also avoids race conditions where the length of the string changes between the realloc() and the readlink().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文