C 言語でファイルの拡張属性を取得する
この記事では、C 言語でファイルの拡張属性を取得する方法のいくつかの方法について説明します。
getxattr
および listxattr
関数を使用して、ファイルの拡張属性を取得する
一部の UNIX ベースのシステムは、ファイルに関連付けることができるメタデータの名前と値のペアを表す、ファイルの拡張属性を提供します。拡張属性には基盤となるファイルシステムのサポートが必要ですが、一般的なファイルシステムタイプにはこの機能があります。拡張属性には、タイプ namespace.name
の特定の形式があります。ここで、namespace
は機能的に類似したものをグループ化するために使用され、name
部分は個々の拡張属性を識別します。名前空間には次の値を指定できます:user
、trusted
、system
、security
。これらは、規則としていくつかの権限タイプを区別します(詳細はページに記載されています)。この場合、コマンドライン引数として複数のファイル名を受け取り、その結果、各ファイルのすべての拡張属性を取得するサンプルプログラムを実装します。プログラムが getopt
関数を使用して複数のファイル引数を処理することに注意してください。
getxattr
関数は、拡張属性値を取得するために 4つの引数を取ります。最初の引数は、EA を取得するファイルを示すファイルシステム内のパスを指定し、2 番目の引数は属性名を指定します。最後の 2つの引数は、getxattr
によって値が格納される場所へのポインタと、このアドレスで使用可能なバッファサイズです。属性値のサイズは、値 0
をサイズ引数として渡すことで取得でき、呼び出しの戻り値は必要なバッファーのバイト数であることに注意してください。ただし、値を取得するために 2 番目の呼び出しが呼び出されると、値が変更されてサイズが異なる場合があります。したがって、エラーコードをチェックして、障害のない実行を保証することをお勧めします。
一方、listxattr
関数は、指定されたファイルパスの拡張属性名のリストを取得します。3つの引数を取り、最初の引数はファイルパスです。次の 2つの引数は、取得したリストが格納されるバッファーと、そのサイズをバイト単位で指定することを表します。このバッファは呼び出し元によって割り当てられ、呼び出し元は十分なメモリを割り当てる責任があることに注意してください。また、getxattr
と同様に、この関数の 3 番目の引数として値 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);
}