Obtenga atributos extendidos de archivo en C

Jinku Hu 12 octubre 2023
  1. Utilice las funciones getxattr y listxattr para obtener atributos extendidos del archivo
  2. Utilice la función setxattr para establecer atributos extendidos en el archivo
Obtenga atributos extendidos de archivo en C

Este artículo explicará varios métodos de cómo obtener atributos extendidos de un archivo en C.

Utilice las funciones getxattr y listxattr para obtener atributos extendidos del archivo

Algunos sistemas basados en UNIX proporcionan atributos extendidos para los archivos, que representan pares de metadatos nombre-valor que pueden asociarse con el archivo. Los atributos extendidos requieren el soporte del sistema de archivos subyacente, pero los tipos de sistemas de archivos comunes tienen esta característica. Los atributos extendidos tienen el formato específico de tipo - namespace.name, donde namespace se utiliza para agrupar otros funcionalmente similares, mientras que la parte de name identifica un atributo extendido individual. Un espacio de nombres puede tener los siguientes valores: user, trusted, system y security, que distinguen varios tipos de permisos como una convención (descritos en detalle en la página). En este caso, implementamos un programa de ejemplo que toma varios nombres de archivo como argumentos de línea de comando y, en consecuencia, recupera todos los atributos extendidos para cada archivo. Observe que el programa procesa los argumentos de varios archivos con la función getopt.

La función getxattr toma cuatro argumentos para recuperar un valor de atributo extendido. El primer argumento especifica una ruta en el sistema de archivos para indicar el archivo para el que se deben recuperar los EA, y el segundo argumento especifica un nombre de atributo. Los dos últimos argumentos son el puntero a la ubicación donde el valor será almacenado por getxattr y el tamaño de búfer disponible en esta dirección. Tenga en cuenta que el tamaño del valor del atributo se puede recuperar pasando el valor 0 como un argumento de tamaño y el valor de retorno de la llamada es el número de bytes para el búfer necesario. Aunque, cuando se invoca la segunda llamada para recuperar el valor, puede cambiar y tener un tamaño diferente; por lo tanto, es mejor verificar los códigos de error para garantizar una ejecución sin fallas.

Por otro lado, la función listxattr recupera la lista de nombres de atributos extendidos para la ruta de archivo dada. Se necesitan tres argumentos, el primero de los cuales es la ruta del archivo. Los siguientes dos argumentos representan el búfer donde se almacenará la lista recuperada y su tamaño especificado en bytes. Tenga en cuenta que este búfer está asignado por la persona que llama, y ​​la persona que llama es responsable de asignar suficiente memoria. Además, de forma similar a getxattr, se puede pasar el valor 0 como tercer argumento a esta función, y el valor devuelto será el tamaño del búfer necesario para almacenar la 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);
}

Utilice la función setxattr para establecer atributos extendidos en el archivo

Alternativamente, podemos establecer atributos arbitrarios a los archivos usando la función setxattr, que toma el nombre de ruta del archivo, el par nombre-valor como argumentos separados, el tamaño del valor, un número entero que especifica los valores predefinidos para diferentes operaciones de conjuntos. Si el último argumento es cero, que es el valor predeterminado, se crea el atributo extendido si no existe; de lo contrario, se reemplaza el valor. La macro XATTR_CREATE se puede especificar para indicar solo la opción de creación, que fallará si el atributo existe, y XATTR_REPLACE para realizar el reemplazo que falla si el atributo no existe.

#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

Artículo relacionado - C File