Как реализовать readlink, чтобы найти путь - PullRequest
21 голосов
/ 03 апреля 2011

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

РЕДАКТИРОВАТЬ: я пытаюсь получить путь к текущей запущенной программе, так же, как вопрос, связанный выше.В ответе на этот вопрос сказано использовать readlink("proc/self/exe").Я не знаю, как реализовать это в моей программе.Я пытался:

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

Это явно неверно.

Ответы [ 4 ]

37 голосов
/ 03 апреля 2011

Это Используйте функцию 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;
}
4 голосов
/ 03 апреля 2011

Давайте посмотрим, что страница руководства говорит:

 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'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 голосов
/ 13 июля 2016

Принятый ответ является почти правильным, за исключением того, что вы не можете полагаться на PATH_MAX, потому что это

гарантированно не будет определено для POSIX, если система не имеет такого ограничение.

(из справочной страницы readlink (2))

Кроме того, когда оно определено, оно не всегда представляет «истинный» предел. (См. http://insanecoding.blogspot.fr/2007/11/pathmax-simply-isnt.html)

Справочная страница readlink также позволяет сделать это по символической ссылке:

Использование статического размера буфера может не обеспечить достаточно места для содержание символической ссылки. Требуемый размер буфера может быть получается из значения stat.st_size, возвращаемого вызовом lstat (2) в ссылка. Тем не менее, число байтов, записанных 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 "";
}
1 голос
/ 22 июля 2011
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

...