Ottieni attributi estesi del file in C

Jinku Hu 12 ottobre 2023
  1. Usa le funzioni getxattr e listxattr per ottenere attributi estesi del file
  2. Usa la funzione setxattr per impostare attributi estesi su file
Ottieni attributi estesi del file in C

Questo articolo spiegherà diversi metodi su come ottenere attributi estesi di un file in C.

Usa le funzioni getxattr e listxattr per ottenere attributi estesi del file

Alcuni sistemi basati su UNIX forniscono attributi estesi per i file, che rappresentano coppie nome-valore di metadati che possono essere associati al file. Gli attributi estesi richiedono il supporto del file system sottostante, ma i tipi di file system comuni hanno questa caratteristica. Gli attributi estesi hanno il formato specifico di tipo - namespace.name, dove namespace è utilizzato per raggruppare quelli funzionalmente simili, mentre la parte name identifica un singolo attributo esteso. Uno spazio dei nomi può avere i seguenti valori: user, trusted, system e security, che distinguono diversi tipi di autorizzazione come convenzione (descritti in dettaglio nella pagina). In questo caso, implementiamo un programma di esempio che accetta più nomi di file come argomenti della linea di comando e di conseguenza recupera tutti gli attributi estesi per ogni file. Si noti che il programma elabora più argomenti di file con la funzione getopt.

La funzione getxattr richiede quattro argomenti per recuperare un valore di attributo esteso. Il primo argomento specifica un percorso nel filesystem per indicare il file per il quale devono essere recuperati gli EA, e il secondo argomento specifica un nome di attributo. Gli ultimi due argomenti sono il puntatore alla posizione in cui il valore verrà memorizzato da getxattr e la dimensione del buffer disponibile su questo indirizzo. Si noti che la dimensione del valore dell’attributo può essere recuperata passando il valore 0 come argomento della dimensione e il valore di ritorno della chiamata è il numero di byte per il buffer necessario. Sebbene, quando la seconda chiamata viene invocata per recuperare il valore, potrebbe essere modificata e avere una dimensione diversa; quindi, è meglio controllare i codici di errore per garantire un’esecuzione senza errori.

D’altra parte, la funzione listxattr recupera l’lista dei nomi degli attributi estesi per il percorso del file specificato. Richiede tre argomenti, il primo dei quali è il percorso del file. I due argomenti successivi rappresentano il buffer in cui verrà memorizzato l’lista recuperato e la sua dimensione specificata in byte. Si noti che questo buffer è allocato al chiamante e il chiamante è responsabile dell’allocazione di memoria sufficiente. Inoltre, in modo simile a getxattr, si può passare il valore 0 come terzo argomento a questa funzione, e il valore restituito sarà la dimensione del buffer necessaria per memorizzare l’lista completo.

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

Usa la funzione setxattr per impostare attributi estesi su file

In alternativa, possiamo impostare attributi arbitrari ai file usando la funzione setxattr, che prende il percorso del file, la coppia nome-valore come argomenti separati, la dimensione del valore, un numero intero che specifica i valori predefiniti per diverse operazioni sugli insiemi. Se l’ultimo argomento è zero, che è il valore predefinito, l’attributo esteso viene creato se non esiste; in caso contrario, il valore viene sostituito. La macro XATTR_CREATE può essere specificata per indicare solo l’opzione di creazione, che fallirà se l’attributo esiste, e XATTR_REPLACE per eseguire la sostituzione che fallisce se l’attributo non esiste.

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

Articolo correlato - C File