Obtenir les attributs étendus du fichier en C

Jinku Hu 12 octobre 2023
  1. Utilisez les fonctions getxattr et listxattr pour obtenir les attributs étendus du fichier
  2. Utilisez la fonction setxattr pour définir les attributs étendus sur le fichier
Obtenir les attributs étendus du fichier en C

Cet article explique plusieurs méthodes pour obtenir des attributs étendus d’un fichier en C.

Utilisez les fonctions getxattr et listxattr pour obtenir les attributs étendus du fichier

Certains systèmes UNIX fournissent des attributs étendus pour les fichiers, représentant des paires nom-valeur de métadonnées pouvant être associées au fichier. Les attributs étendus nécessitent la prise en charge du système de fichiers sous-jacent, mais les types de systèmes de fichiers courants ont cette fonctionnalité. Les attributs étendus ont le format spécifique de type - namespace.name, où namespace est utilisé pour regrouper des attributs fonctionnellement similaires, tandis que la partie name identifie un attribut étendu individuel. Un espace de noms peut avoir les valeurs suivantes: user, trusted, system et security, qui distinguent plusieurs types d’autorisations par convention (décrit en détail sur la page). Dans ce cas, nous implémentons un exemple de programme qui prend plusieurs noms de fichiers comme arguments de ligne de commande et récupère par conséquent tous les attributs étendus pour chaque fichier. Notez que le programme traite les multiples arguments du fichier avec la fonction getopt.

La fonction getxattr prend quatre arguments pour récupérer une valeur d’attribut étendue. Le premier argument spécifie un chemin dans le système de fichiers pour indiquer le fichier pour lequel les EA doivent être récupérés, et le second argument spécifie un nom d’attribut. Les deux derniers arguments sont le pointeur vers l’emplacement où la valeur sera stockée par getxattr et la taille du buffer disponible sur cette adresse. Notez que la taille de la valeur d’attribut peut être récupérée en passant la valeur 0 comme argument de taille et la valeur de retour de l’appel est le nombre d’octets pour le tampon nécessaire. Bien que, lorsque le deuxième appel est appelé pour récupérer la valeur, il peut être modifié et avoir une taille différente; il est donc préférable de vérifier les codes d’erreur pour garantir une exécution sans faute.

Par contre, la fonction listxattr récupère la liste des noms d’attributs étendus pour le chemin de fichier donné. Il prend trois arguments, dont le premier est le chemin du fichier. Les deux arguments suivants représentent le tampon dans lequel la liste récupérée sera stockée et sa taille spécifiée en octets. Notez que cette mémoire tampon est allouée à l’appelant et que l’appelant est responsable d’allouer suffisamment de mémoire. De plus, comme pour le getxattr, on peut passer la valeur 0 comme troisième argument à cette fonction, et la valeur retournée sera la taille du tampon nécessaire pour stocker la liste complète.

#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);
}

Utilisez la fonction setxattr pour définir les attributs étendus sur le fichier

Alternativement, nous pouvons définir des attributs arbitraires pour les fichiers en utilisant la fonction setxattr, qui prend le chemin du fichier, la paire nom-valeur comme arguments séparés, la taille de la valeur, un entier qui spécifie les valeurs prédéfinies pour différentes opérations d’ensemble. Si le dernier argument est zéro, qui est la valeur par défaut, l’attribut étendu est créé s’il n’existe pas; sinon, la valeur est remplacée. La macro XATTR_CREATE peut être spécifiée pour indiquer uniquement l’option de création, qui échouera si l’attribut existe, et XATTR_REPLACE pour effectuer un remplacement qui échoue si l’attribut n’existe pas.

#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);
}
Auteur: 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

Article connexe - C File