Linux 如何实现readlink来查找路径
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5525668/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to implement readlink to find the path
提问by a sandwhich
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?
使用 readlink 函数作为解决方案如何在 C 中找到可执行文件的位置?,如何将路径放入字符数组?另外,变量 buf 和 bufsize 代表什么以及如何初始化它们?
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:
编辑:我正在尝试获取当前正在运行的程序的路径,就像上面链接的问题一样。该问题的答案说使用readlink("proc/self/exe")
. 我不知道如何在我的程序中实现它。我试过:
char buf[1024];
string var = readlink("/proc/self/exe", buf, bufsize);
This is obviously incorrect.
这显然是不正确的。
采纳答案by Mat
This Use the readlink() function properlyfor the correct uses of the readlink
function.
这使用的readlink()函数正确的正确使用readlink
功能。
If you have your path in a std::string
, you could do something like this:
如果你在 a 中有你的路径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] = 'std::string get_selfpath() {
char buff[PATH_MAX];
ssize_t len = ::readlink("/proc/self/exe", buff, sizeof(buff)-1);
if (len != -1) {
buff[len] = 'int main()
{
std::string selfpath = get_selfpath();
std::cout << selfpath << std::endl;
return 0;
}
';
return std::string(buff);
}
/* handle error condition */
}
';
return std::string(buff);
}
/* handle error condition */
}
If you're only after a fixed path:
如果您只追求固定路径:
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.
To use it:
要使用它:
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;
}
回答by asveikau
Let's look at what the manpagesays:
让我们看看联机帮助页是怎么说的:
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;
}
}
OK. Should be simple enough. Given your buffer of 1024 chars:
好的。应该足够简单了。给定 1024 个字符的缓冲区:
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] = '#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;
}
';
return (std::string(&(buf[0])));
}
/* handle error */
return "";
}
回答by onelineproof
回答by Wddysr
Accepted answer is almost correct, except you can't rely on PATH_MAX because it is
接受的答案几乎是正确的,除非您不能依赖 PATH_MAX,因为它是
not guaranteed to be defined per POSIX if the system does not have such limit.
如果系统没有这样的限制,则不能保证按 POSIX 定义。
(From readlink(2) manpage)
(来自 readlink(2) 联机帮助页)
Also, when it's defined it doesn't always represent the "true" limit. (See http://insanecoding.blogspot.fr/2007/11/pathmax-simply-isnt.html)
此外,当它被定义时,它并不总是代表“真实”的限制。(见http://insanecoding.blogspot.fr/2007/11/pathmax-simply-isnt.html)
The readlink's manpage also give a way to do that on symlink :
readlink 的联机帮助页还提供了一种在 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.
使用静态大小的缓冲区可能无法为符号链接内容提供足够的空间。缓冲区所需的大小可以从在链接上调用 lstat(2) 返回的 stat.st_size 值中获得。但是,应该检查 readlink() 和 readlinkat() 写入的字节数,以确保符号链接的大小在两次调用之间没有增加。
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.
但是,在 /proc/self/exe/ 的情况下,对于大多数 /proc 文件,stat.st_size 将为 0。我看到的唯一剩余解决方案是在不适合的情况下调整缓冲区大小。
I suggest the use of vector<char>
as follow for this purpose:
vector<char>
为此,我建议使用以下方法:
回答by Lassi
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.
这使用了传统的“当您不知道正确的缓冲区大小时,重新分配 2 的递增幂”技巧。我们假设为路径名分配少于 64 个字节是不值得的。我们还假设一个长达 16384 (2**14) 个字节的可执行路径名必须表明程序的安装方式存在某种异常,并且知道路径名并没有用,因为我们很快就会遇到更大的问题需要担心关于。
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()
.
没有必要打扰像PATH_MAX
. 保留如此多的内存对于几乎所有路径名来说都是多余的,并且如另一个答案中所述,无论如何都不能保证它是实际的上限。对于这个应用,我们可以选择一个常识上限,比如 16384。即使对于没有常识上限的应用,重新分配 2 的递增幂也是一个很好的方法。你只需要log n
调用一个n
-byte 结果,你浪费的内存容量与结果的长度成正比。它还避免了字符串长度在realloc()
和之间变化的竞争条件readlink()
。