Как реализовать readlink для поиска пути
Использование функции readlink, используемой в качестве решения для Как найти местоположение исполняемого файла в C?, как мне получить путь в char массив? Кроме того, что представляют переменные buf и bufsize и как их инициализировать?
EDIT: Я пытаюсь получить путь к текущей запущенной программе, как и связанный выше вопрос. Ответ на этот вопрос сказал использовать readlink("proc/self/exe")
. Я не знаю, как реализовать это в моей программе. Я пробовал:
char buf[1024];
string var = readlink("/proc/self/exe", buf, bufsize);
Это, очевидно, неверно.
Ответы
Ответ 1
Этот правильно использовать функцию 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;
}
Ответ 2
Посмотрите, что 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.
OK. Должно быть достаточно простым. Учитывая ваш буфер из 1024 символов:
char buf[1024];
/* The manpage says it won't null terminate. Let 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;
}
Ответ 3
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
Принятый ответ почти правильный, за исключением того, что вы не можете полагаться на PATH_MAX, потому что он
не гарантируется для каждого POSIX, если в системе нет таких предел.
(Из справочной страницы readlink (2))
Кроме того, когда он определяет, он не всегда представляет собой "истинный" предел. (См. http://insanecoding.blogspot.fr/2007/11/pathmax-simply-isnt.html)
В man-ссылке readlink также предоставляется способ сделать это в symlink:
Использование статического размера буфера может не обеспечить достаточного пространства для символическое содержание ссылки. Необходимый размер для буфера может быть полученное из значения stat.st_size, возвращаемого вызовом lstat (2) on связь. Однако количество байтов, написанных readlink() и read- linkat() следует проверить, чтобы убедиться, что размер символического ссылка не увеличивалась между вызовами.
Однако в случае/proc/self/exe/как для большинства файлов proc, stat.st_size будет равен 0. Единственное оставшееся решение, которое я вижу, это изменить размер буфера, пока он не подходит.
Я предлагаю использовать 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 "";
}