用 C 語言獲取檔案的擴充套件屬性

Jinku Hu 2023年10月12日
  1. 使用 getxattrlistxattr 函式獲取檔案的擴充套件屬性
  2. 使用 setxattr 函式來設定檔案的擴充套件屬性
用 C 語言獲取檔案的擴充套件屬性

本文將介紹幾種如何在 C 語言中獲取檔案擴充套件屬性的方法。

使用 getxattrlistxattr 函式獲取檔案的擴充套件屬性

一些基於 UNIX 的系統為檔案提供擴充套件的屬性,表示可以與檔案關聯的後設資料的名稱/值對。擴充套件屬性需要基礎檔案系統支援,但是常見檔案系統型別具有此功能。擴充套件屬性具有 namespace.name 型別的特定格式,其中 namespace 用於對功能相似的分組,而 name 部分則標識單個擴充套件屬性。名稱空間可以具有以下值:usertrustedsystemsecurity,作為一種慣例,它們區分了幾種許可權型別(在這裡有詳細描述)。在這種情況下,我們實現了一個例子程式,該程式將多個檔名用作命令列引數,並因此為每個檔案檢索所有擴充套件屬性。請注意,該程式使用 getopt 函式處理多個檔案引數。

getxattr 函式採用四個引數來檢索擴充套件的屬性值。第一個引數指定檔案系統中的路徑,以指示應為其檢索 EA 的檔案,第二個引數指定屬性名稱。最後兩個引數是指向由 getxattr 儲存值的位置的指標,以及該地址上可用的緩衝區大小。請注意,可以通過將值 0 作為大小引數傳遞來檢索屬性值的大小,並且呼叫的返回值是所需緩衝區的位元組數。儘管在呼叫第二個呼叫以檢索該值時,它可能會更改並且大小不同;因此,最好檢查錯誤程式碼以確保無誤執行。

另一方面,listxattr 函式檢索給定檔案路徑的擴充套件屬性名稱列表。它包含三個引數,第一個是檔案路徑。接下來的兩個參數列示將儲存檢索到的列表的緩衝區,緩衝區的大小以位元組為單位。請注意,此緩衝區是由呼叫方分配的,並且呼叫方負責分配足夠的記憶體。同樣,類似於 getxattr,可以將值 0 作為該函式的第三個引數傳遞,返回值將是儲存完整列表所需的緩衝區大小。

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

使用 setxattr 函式來設定檔案的擴充套件屬性

另外,我們可以使用 setxattr 函式為檔案設定任意屬性,該函式將檔案的路徑名,名稱/值對作為單獨的引數,值的大小,一個整數,該整數指定不同設定操作的預定義值。如果最後一個引數為零(預設值),則擴充套件屬性(如果不存在)將建立;否則,擴充套件屬性將被建立。否則,將替換該值。可以指定 XATTR_CREATE 巨集以指示僅建立選項,如果該屬性存在則將失敗,而可以指定 XATTR_REPLACE 進行替換,如果該屬性不存在則將失敗。

#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);
}
作者: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

DelftStack.com 創辦人。Jinku 在機器人和汽車行業工作了8多年。他在自動測試、遠端測試及從耐久性測試中創建報告時磨練了自己的程式設計技能。他擁有電氣/ 電子工程背景,但他也擴展了自己的興趣到嵌入式電子、嵌入式程式設計以及前端和後端程式設計。

LinkedIn Facebook

相關文章 - C File