Подтвердить что ты не робот

Как реализовать readlink для поиска пути

Использование функции readlink, используемой в качестве решения для Как найти местоположение исполняемого файла в C?, как мне получить путь в char массив? Кроме того, что представляют переменные buf и bufsize и как их инициализировать?

EDIT: Я пытаюсь получить путь к текущей запущенной программе, как и связанный выше вопрос. Ответ на этот вопрос сказал использовать readlink("proc/self/exe"). Я не знаю, как реализовать это в моей программе. Я пробовал:

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

Это, очевидно, неверно.

4b9b3361

Ответ 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 "";
}