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

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

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

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

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

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

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

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#include <sys/xattr.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);
}
Author: 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

相關文章 - C File