Obtenha atributos estendidos de arquivo em C

Jinku Hu 12 outubro 2023
  1. Use as funções getxattr e listxattr para obter atributos estendidos do arquivo
  2. Use a função setxattr para definir atributos estendidos no arquivo
Obtenha atributos estendidos de arquivo em C

Este artigo explicará vários métodos de como obter atributos estendidos de um arquivo em C.

Use as funções getxattr e listxattr para obter atributos estendidos do arquivo

Alguns sistemas baseados em UNIX fornecem atributos estendidos para os arquivos, representando pares nome-valor de metadados que podem ser associados ao arquivo. Os atributos estendidos requerem o suporte do sistema de arquivos subjacente, mas os tipos de sistemas de arquivos comuns têm esse recurso. Os atributos estendidos têm o formato específico do tipo - namespace.name, em que namespace é utilizado para agrupar outros funcionalmente semelhantes, enquanto a parte name identifica um atributo estendido individual. Um namespace pode ter os seguintes valores: user, trusted, system e security, que distinguem vários tipos de permissão como uma convenção (descrito em detalhes na página). Nesse caso, implementamos um programa de exemplo que recebe vários nomes de arquivos como argumentos de linha de comando e, consequentemente, recupera todos os atributos estendidos para cada arquivo. Observe que o programa processa os vários argumentos do arquivo com a função getopt.

A função getxattr leva quatro argumentos para recuperar um valor de atributo estendido. O primeiro argumento especifica um caminho no sistema de arquivos para indicar o arquivo para o qual os EAs devem ser recuperados, e o segundo argumento especifica um nome de atributo. Os dois últimos argumentos são o ponteiro para o local onde o valor será armazenado por getxattr e o tamanho do buffer disponível neste endereço. Observe que o tamanho do valor do atributo pode ser recuperado passando o valor 0 como um argumento de tamanho e o valor de retorno da chamada é o número de bytes para o buffer necessário. Embora, quando a segunda chamada é chamada para recuperar o valor, ele pode ser alterado e ter um tamanho diferente; portanto, é melhor verificar os códigos de erro para garantir uma execução sem falhas.

Por outro lado, a função listxattr recupera a lista de nomes de atributos estendidos para o caminho de arquivo fornecido. Leva três argumentos, o primeiro dos quais é o caminho do arquivo. Os próximos dois argumentos representam o buffer onde a lista recuperada será armazenada e seu tamanho especificado em bytes. Observe que esse buffer é alocado pelo chamador e o chamador é responsável por alocar memória suficiente. Além disso, semelhante ao getxattr, pode-se passar o valor 0 como o terceiro argumento para esta função, e o valor retornado será o tamanho do buffer necessário para armazenar a lista completa.

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/xattr.h>
#include <unistd.h>

#define XATTR_SIZE 10000

#define errExit(msg)    \
  do {                  \
    perror(msg);        \
    exit(EXIT_FAILURE); \
  } while (0)

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;
  bool 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 char)value[k]);
      }

      printf("\n");
    }

    printf("\n");
  }

  exit(EXIT_SUCCESS);
}

Use a função setxattr para definir atributos estendidos no arquivo

Alternativamente, podemos definir atributos arbitrários para os arquivos usando a função setxattr, que leva o nome do caminho do arquivo, par nome-valor como argumentos separados, o tamanho do valor, um inteiro que especifica os valores predefinidos para diferentes operações de conjunto. Se o último argumento for zero, que é o valor padrão, o atributo estendido será criado se não existir; caso contrário, o valor é substituído. A macro XATTR_CREATE pode ser especificada para indicar apenas a opção de criação, que falhará se o atributo existir, e XATTR_REPLACE para realizar a substituição que falha se o atributo não existir.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/xattr.h>

#define errExit(msg)    \
  do {                  \
    perror(msg);        \
    exit(EXIT_FAILURE); \
  } while (0)

static void usageError(char *progName) {
  fprintf(stderr, "Usage: %s file\n", progName);
  exit(EXIT_FAILURE);
}

int main(int argc, char *argv[]) {
  char *value;

  if (argc < 2 || strcmp(argv[1], "--help") == 0) usageError(argv[0]);

  value = "x attribute value";
  if (setxattr(argv[1], "user.x", value, strlen(value), 0) == -1)
    errExit("setxattr");

  value = "y attribute value";
  if (setxattr(argv[1], "user.y", value, strlen(value), 0) == -1)
    errExit("setxattr");

  exit(EXIT_SUCCESS);
}
Autor: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

Artigo relacionado - C File