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

StackOverflow https://stackoverflow.com/questions/9385386

  •  28-10-2019
  •  | 
  •  

Вопрос

Проблема:

На Linux-машине я хочу прочитать целевую строку ссылки.Из документации я нашел следующий образец кода (без обработки ошибок):

родовое слово

Проблема в том, что sb.st_size возвращает 0 для ссылок в моей системе.

Так как же в таких системах динамически выделять память для строки чтения?

Большое спасибо!


Одно из возможных решений:

Для дальнейшего использования.Используя точку зрения Джилля:

родовое слово
Это было полезно?

Решение

POSIX сообщает, что поле st_size для символической ссылки должно быть установлено равным длине имени пути в ссылке (без кода '\0').Однако файловая система /proc в Linux не совместима с POSIX.(У него больше нарушений, чем только это, например, при чтении определенных файлов по одному байту.)

Вы можете выделить буфер определенного размера, попробовать сгенерировать код и повторить попытку с большим буфером, если буфер был недостаточно велик (сгенерированный код кода вернул столько байтов, сколько поместилось в буфере), пока буфер не станет достаточно большим.

В качестве альтернативы вы можете использовать readlink() и нарушить переносимость в системы, где он не является константой времени компиляции или где имя пути может быть длиннее этого (POSIX допускает и то).

Другие советы

В других ответах об этом не упоминается, но есть функция realpath, которая делает именно то, что вы хотите, что указано в POSIX.1-2001.

родовое слово

со страницы руководства:

<цитата>

realpath () раскрывает все символические ссылки и разрешает ссылки на /./, /../ и дополнительные символы '/' в строке с завершающим нулем с именем по пути для создания канонического абсолютного пути.

realpath также обрабатывает распределение динамической памяти за вас, если вы хотите.Опять же, отрывок из справочной страницы:

<цитата>

Если resolved_path указано как NULL, то realpath () использует malloc (3) для выделения буфера размером до PATH_MAX байтов для хранения разрешенное имя пути и возвращает указатель на этот буфер.Звонящий должен освободить этот буфер с помощью free (3).

В качестве простого полного примера:

родовое слово

st_size не дает правильный ответ на / proc.

Вместо этого вы можете указать байты PATH_MAX или pathconf (_PC_PATH_MAX).В большинстве случаев этого должно быть достаточно.Если вы хотите иметь возможность обрабатывать более длинные пути, вы можете вызвать readlink в цикле и перераспределить свой буфер, если возвращаемое значение readlink указывает, что буфер слишком короткий.Обратите внимание, что многие другие функции POSIX просто предполагают, что PATH_MAX достаточно.

Я немного озадачен, почему st_size равен нулю. В POSIX:

<цитата>

Для символических ссылок член st_mode должен содержать значимую информацию при использовании с макросами типа файла. Биты режима файла в st_mode не определены. Элементы структуры st_ino, st_dev, st_uid, st_gid, st_atim, st_ctim и st_mtim должны иметь значимые значения, а значение члена st_nlink должно быть установлено равным количеству (жестких) ссылок на символическую ссылку. Значение элемента st_size должно быть установлено равным длине имени пути, содержащегося в символической ссылке, не включая завершающий нулевой байт.

Источник: http://pubs.opengroup.org/onlinepubs/9699919799/ functions / lstat.html

Если st_size не работает, я думаю, ваш единственный вариант - динамически выделить буфер и продолжать увеличивать его размер до тех пор, пока возвращаемое значение readlink равно размеру буфера.

На странице руководства для readlink(2) написано, что она будет автоматически обрезаться, если буфер слишком мал.Если вы действительно хотите быть неограниченным (и не против заплатить некоторую плату за дополнительную работу), вы можете начать с заданного размера выделения и продолжать увеличивать его и повторно пробовать вызов readlink.Вы можете остановить увеличение буфера, когда следующий вызов readlink вернет ту же строку, что и на последней итерации.

Чего именно вы пытаетесь достичь с помощью lstat?

Вы сможете достичь цели с помощью следующих

родовое слово

Если вы пытаетесь получить длину размера имени файла, я не думаю, что st_size - правильная переменная для этого ... Но, возможно, это другой вопрос.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top