int fremovexattr(int
Все вызовы возвращают 0 при успешном завершении и –1 при ошибке
Строка с завершающим нулем, переданная аргументу name, идентифицирует EA, который нужно удалить. Попытка удаления несуществующего атрибута приведет к ошибке ENODATA.
Системные вызовы listxattr(), llistxattr() и flistxattr() возвращают список, содержащий имена всех расширенных атрибутов, связанных с файлом.
#include
ssize_t listxattr(const char *
ssize_t llistxattr(const char *
ssize_t flistxattr(int
Все вызовы при успешном завершении возвращают количество байтов, скопированных в список, или –1 при ошибке
Список имен расширенных атрибутов возвращается в виде последовательности строк с завершающим нулем в буфер, на который указывает аргумент list. Размер данного буфера должен быть задан в аргументе size. При успешном завершении эти системные вызовы возвращают количество байтов, скопированных в список list.
У системного вызова getxattr() можно указать нулевое значение аргумента size. В таком случае аргумент list игнорируется, однако система может вернуть размер буфера, который мог бы понадобиться для последующего вызова, чтобы на самом деле извлечь список имен расширенных атрибутов (предполагая, что он не изменился).
Для извлечения списка имен EA, связанных с файлом, необходимо лишь обеспечить доступность файла (то есть у нас должно быть право доступа на выполнение ко всем каталогам, которые есть в имени пути). Никаких прав доступа к самому файлу не требуется.
По соображениям безопасности из перечня расширенных атрибутов, приводящихся в списке list, могут быть исключены атрибуты, для доступа к которым у вызывающего процесса нет прав. Например, многие системы не включают атрибуты trusted в список, возвращаемый системным вызовом listxattr(), выполненным непривилегированным процессом. Однако заметьте: в предыдущем предложении сказано «могут быть исключены» — это указывает на то, что какая-либо реализация файловой системы не обязана так поступать. Следовательно, необходимо допускать возможность того, что при последующем системном вызове getxattr(), использующем имя расширенного атрибута из списка list, может произойти ошибка, поскольку данный процесс не обладает привилегиями, необходимыми для получения значения этого атрибута. (Подобная ошибка могла бы произойти также в том случае, если бы другой процесс удалил какой-либо атрибут между моментами вызовов listxattr() и getxattr().)
Приведенная в листинге 16.1 программа извлекает и отображает имена и значения всех расширенных атрибутов файлов, перечисленных в командной строке. Для каждого файла программа задействует системный вызов listxattr(), чтобы извлечь имена всех EA, связанных с данным файлом, а затем осуществляет цикл, выполняя системный вызов getxattr() для каждого имени, чтобы извлечь соответствующее значение. По умолчанию значения атрибутов отображаются как простой текст. Если указать параметр — x, то значения атрибутов будут отображаться как шестнадцатеричные строки. Приведенный ниже сеанс работы в оболочке демонстрирует использование данной программы:
$ setfattr — n user.x — v "The past is not dead." Tfile
$ setfattr — n user.y — v "In fact, it's not even past." Tfile
$ ./xattr_view tfile
tfile:
name=user.x; value=The past is not dead.
Name=user.y; value=In fact, it's not even past.
Листинг 16.1. Отображение расширенных атрибутов файла
xattr/xattr_view.c
#include
#include "tlpi_hdr.h"
#define XATTR_SIZE 10000
static void
usageError(char *progName)
{
fprintf(stderr, "Usage: %s [-x] file…\n", progName);
exit(EXIT_FAILURE);
}
int
main(int argc, char *argv[])
{
char list[XATTR_SIZE], value[XATTR_SIZE];
ssize_t listLen, valueLen;
int ns, j, k, opt;
Boolean hexDisplay;
hexDisplay = 0;
while ((opt = getopt(argc, argv, "x"))!= -1) {
switch (opt) {
case 'x': hexDisplay = 1; break;
case '?': usageError(argv[0]);
}
}
if (optind >= argc)
usageError(argv[0]);
for (j = optind; j < argc; j++) {
listLen = listxattr(argv[j], list, XATTR_SIZE);
if (listLen == -1)
errExit("listxattr");
printf("%s: \n", argv[j]);
for (ns = 0; ns < listLen; ns += strlen(&list[ns]) + 1) {
printf(" name=%s; ", &list[ns]);
valueLen = getxattr(argv[j], &list[ns], value, XATTR_SIZE);
if (valueLen == -1) {
printf("couldn't get value");
} else if (!hexDisplay) {
printf("value=%.*s", (int) valueLen, value);
} else {
printf("value=");
for (k = 0; k < valueLen; k++)
printf("%02x", (unsigned int) value[k]);
}
printf("\n");
}
printf("\n");
}
exit(EXIT_SUCCESS);
}
xattr/xattr_view.c