Erweiterte Dateiattribute in C abrufen

Jinku Hu 12 Oktober 2023
  1. Verwenden Sie die Funktionen getxattr und listxattr, um erweiterte Dateiattribute abzurufen
  2. Verwenden Sie die Funktion setxattr, um erweiterte Attribute für Dateien festzulegen
Erweiterte Dateiattribute in C abrufen

In diesem Artikel werden verschiedene Methoden zum Abrufen erweiterter Attribute einer Datei in C erläutert.

Verwenden Sie die Funktionen getxattr und listxattr, um erweiterte Dateiattribute abzurufen

Einige UNIX-basierte Systeme bieten erweiterte Attribute für die Dateien, die Name-Wert-Paare von Metadaten darstellen, die der Datei zugeordnet werden können. Erweiterte Attribute erfordern die zugrunde liegende Dateisystemunterstützung, aber die gängigen Dateisystemtypen verfügen über diese Funktion. Erweiterte Attribute haben das spezifische Format vom Typ - namespace.name, wobei namespace verwendet wird, um funktional ähnliche zu gruppieren, während der Teil name ein einzelnes erweitertes Attribut identifiziert. Ein Namespace kann die folgenden Werte haben: user, trusted, system und security, die als Konvention mehrere Berechtigungstypen unterscheiden (ausführlich beschrieben auf Seite). In diesem Fall implementieren wir ein Beispielprogramm, das mehrere Dateinamen als Befehlszeilenargumente verwendet und folglich alle erweiterten Attribute für jede Datei abruft. Beachten Sie, dass das Programm die mehreren Dateiargumente mit der Funktion getopt verarbeitet.

Die Funktion getxattr benötigt vier Argumente, um einen erweiterten Attributwert abzurufen. Das erste Argument gibt einen Pfad im Dateisystem an, der die Datei angibt, für die EAs abgerufen werden sollen, und das zweite Argument gibt einen Attributnamen an. Die letzten beiden Argumente sind der Zeiger auf die Stelle, an der der Wert von getxattr gespeichert wird, und die verfügbare Puffergröße für diese Adresse. Beachten Sie, dass die Größe des Attributwerts abgerufen werden kann, indem der Wert 0 als Größenargument übergeben wird. Der Rückgabewert des Aufrufs ist die Anzahl der Bytes für den benötigten Puffer. Wenn der zweite Aufruf zum Abrufen des Werts aufgerufen wird, kann er jedoch geändert werden und eine andere Größe haben. Daher ist es besser, nach den Fehlercodes zu suchen, um eine fehlerfreie Ausführung zu gewährleisten.

Andererseits ruft die Funktion listxattr die Liste der erweiterten Attributnamen für den angegebenen Dateipfad ab. Es werden drei Argumente benötigt, von denen das erste der Dateipfad ist. Die nächsten beiden Argumente stellen den Puffer dar, in dem die abgerufene Liste gespeichert und ihre Größe in Bytes angegeben wird. Beachten Sie, dass dieser Puffer vom Anrufer zugewiesen wird und der Anrufer für die Zuweisung von ausreichend Speicher verantwortlich ist. Ähnlich wie bei getxattr kann man auch den Wert 0 als drittes Argument an diese Funktion übergeben, und der zurückgegebene Wert ist die Puffergröße, die zum Speichern der vollständigen Liste erforderlich ist.

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

Verwenden Sie die Funktion setxattr, um erweiterte Attribute für Dateien festzulegen

Alternativ können wir mit der Funktion setxattr beliebige Attribute für die Dateien festlegen. Dabei werden der Pfadname, das Name-Wert-Paar der Datei als separate Argumente, die Größe des Werts und eine Ganzzahl verwendet, die die vordefinierten Werte für verschiedene Set-Operationen angibt. Wenn das letzte Argument Null ist, was der Standardwert ist, wird das erweiterte Attribut erstellt, wenn es nicht vorhanden ist. Andernfalls wird der Wert ersetzt. Das Makro XATTR_CREATE kann angegeben werden, um nur die Erstellungsoption anzugeben, die fehlschlägt, wenn das Attribut vorhanden ist, und XATTR_REPLACE, um eine Ersetzung durchzuführen, die fehlschlägt, wenn das Attribut nicht vorhanden ist.

#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

Verwandter Artikel - C File