llistxattr函数详解 Link to heading

1. 函数介绍 Link to heading

llistxattr函数是Linux系统中用于列出文件扩展属性名称的函数。它是extended attributes(扩展属性)API的一部分,专门用于处理符号链接文件的扩展属性。可以把llistxattr想象成一个"扩展属性清单查看器",它能够列出指定符号链接文件所拥有的所有扩展属性的名称。

扩展属性是Linux文件系统的一个特性,允许用户为文件关联额外的元数据信息。这些属性可以用于存储访问控制信息、安全标签、用户自定义数据等。与传统的文件属性(如权限、所有者、时间戳)不同,扩展属性提供了更灵活的元数据存储机制。

llistxattr与listxattr的区别

  • listxattr: 跟随符号链接,操作目标文件
  • llistxattr: 不跟随符号链接,操作符号链接本身

使用场景:

  • 安全系统中的访问控制标签管理
  • 文件系统元数据管理
  • 备份和同步工具的属性处理
  • 系统审计和监控
  • 容器和虚拟化环境的属性管理

2. 函数原型 Link to heading

#include <sys/types.h>
#include <attr/xattr.h>

ssize_t llistxattr(const char *path, char *list, size_t size);

3. 功能 Link to heading

llistxattr函数的主要功能是列出指定符号链接文件的所有扩展属性名称。它不跟随符号链接,而是直接操作符号链接文件本身,获取其扩展属性列表。

4. 参数 Link to heading

  • path: 文件路径名

    • 类型:const char*
    • 含义:要列出扩展属性的符号链接文件路径名
  • list: 属性名称缓冲区

    • 类型:char*
    • 含义:用于存储扩展属性名称列表的缓冲区
    • 如果为NULL,则返回所需的缓冲区大小
  • size: 缓冲区大小

    • 类型:size_t
    • 含义:list缓冲区的大小(字节数)

5. 返回值 Link to heading

  • 成功:
    • 如果list不为NULL:返回实际写入list缓冲区的字节数
    • 如果list为NULL:返回所需的缓冲区大小
  • 失败: 返回-1,并设置errno错误码
    • ENOATTR/ENODATA:文件没有扩展属性
    • ENOTSUP:文件系统不支持扩展属性
    • EACCES:权限不足
    • EFAULT:path或list指向无效内存
    • EIO:I/O错误
    • ELOOP:符号链接循环
    • ENAMETOOLONG:路径名过长
    • ENOENT:文件不存在
    • ENOTDIR:路径前缀不是目录
    • EPERM:操作不被允许

6. 相似函数或关联函数 Link to heading

  • listxattr(): 列出文件扩展属性(跟随符号链接)
  • getxattr(): 获取扩展属性值
  • setxattr(): 设置扩展属性值
  • removexattr(): 删除扩展属性
  • lgetxattr(): 获取符号链接扩展属性值
  • lsetxattr(): 设置符号链接扩展属性值
  • lremovexattr(): 删除符号链接扩展属性
  • flistxattr(): 通过文件描述符列出扩展属性

7. 示例代码 Link to heading

示例1:基础llistxattr使用 - 符号链接扩展属性列表 Link to heading

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <attr/xattr.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>

// 创建测试环境
int create_test_environment() {
    printf("创建测试环境...\n");
    
    // 创建测试文件
    int fd = open("test_file.txt", O_CREAT | O_WRONLY | O_TRUNC, 0644);
    if (fd != -1) {
        const char* content = "这是测试文件内容\n";
        write(fd, content, strlen(content));
        close(fd);
        printf("创建测试文件: test_file.txt\n");
    }
    
    // 创建符号链接
    if (symlink("test_file.txt", "test_symlink") == 0) {
        printf("创建符号链接: test_symlink -> test_file.txt\n");
    }
    
    // 为原文件设置扩展属性
    const char* file_attrs[] = {
        "user.comment",
        "user.author",
        "trusted.security_label"
    };
    
    const char* file_values[] = {
        "测试文件注释",
        "张三",
        "SECURE"
    };
    
    printf("为原文件设置扩展属性:\n");
    for (int i = 0; i < 3; i++) {
        if (setxattr("test_file.txt", file_attrs[i], file_values[i], 
                     strlen(file_values[i]), 0) == 0) {
            printf("  设置 %s = %s\n", file_attrs[i], file_values[i]);
        } else {
            printf("  设置 %s 失败: %s\n", file_attrs[i], strerror(errno));
        }
    }
    
    // 为符号链接设置扩展属性
    const char* link_attrs[] = {
        "user.link_comment",
        "user.link_target"
    };
    
    const char* link_values[] = {
        "符号链接注释",
        "指向test_file.txt"
    };
    
    printf("为符号链接设置扩展属性:\n");
    for (int i = 0; i < 2; i++) {
        if (lsetxattr("test_symlink", link_attrs[i], link_values[i], 
                      strlen(link_values[i]), 0) == 0) {
            printf("  设置 %s = %s\n", link_attrs[i], link_values[i]);
        } else {
            printf("  设置 %s 失败: %s\n", link_attrs[i], strerror(errno));
        }
    }
    
    return 0;
}

// 解析和显示扩展属性列表
void display_xattr_list(const char* filename, const char* list, ssize_t list_size) {
    printf("文件 '%s' 的扩展属性列表:\n", filename);
    
    if (list_size <= 0) {
        if (list_size == 0) {
            printf("  (无扩展属性)\n");
        } else {
            printf("  获取扩展属性列表失败: %s\n", strerror(errno));
        }
        return;
    }
    
    // 解析属性名称列表
    const char* ptr = list;
    int attr_count = 0;
    
    while (ptr < list + list_size) {
        size_t attr_len = strlen(ptr);
        if (attr_len > 0) {
            printf("  %s\n", ptr);
            attr_count++;
            ptr += attr_len + 1;  // 跳过属性名和结尾的null字符
        } else {
            ptr++;
        }
    }
    
    printf("  总计: %d 个扩展属性\n\n", attr_count);
}

int main() {
    printf("=== 基础llistxattr使用示例 ===\n");
    
    // 创建测试环境
    if (create_test_environment() == -1) {
        exit(EXIT_FAILURE);
    }
    
    // 演示listxattr和llistxattr的区别
    printf("\n1. 演示listxattr和llistxattr的区别:\n");
    
    // 首先获取所需的缓冲区大小
    printf("获取原文件扩展属性列表大小:\n");
    ssize_t file_list_size = listxattr("test_file.txt", NULL, 0);
    if (file_list_size == -1) {
        printf("  获取大小失败: %s\n", strerror(errno));
    } else {
        printf("  所需缓冲区大小: %zd 字节\n", file_list_size);
        
        // 分配缓冲区并获取属性列表
        if (file_list_size > 0) {
            char* file_list = malloc(file_list_size);
            if (file_list) {
                ssize_t result = listxattr("test_file.txt", file_list, file_list_size);
                if (result != -1) {
                    display_xattr_list("test_file.txt", file_list, result);
                } else {
                    printf("获取原文件属性列表失败: %s\n", strerror(errno));
                }
                free(file_list);
            }
        }
    }
    
    // 获取符号链接本身的扩展属性列表
    printf("获取符号链接扩展属性列表大小:\n");
    ssize_t link_list_size = llistxattr("test_symlink", NULL, 0);
    if (link_list_size == -1) {
        printf("  获取大小失败: %s\n", strerror(errno));
    } else {
        printf("  所需缓冲区大小: %zd 字节\n", link_list_size);
        
        // 分配缓冲区并获取属性列表
        if (link_list_size > 0) {
            char* link_list = malloc(link_list_size);
            if (link_list) {
                ssize_t result = llistxattr("test_symlink", link_list, link_list_size);
                if (result != -1) {
                    display_xattr_list("test_symlink", link_list, result);
                } else {
                    printf("获取符号链接属性列表失败: %s\n", strerror(errno));
                }
                free(link_list);
            }
        }
    }
    
    // 比较两种方式的结果
    printf("2. 比较结果:\n");
    printf("  listxattr('test_file.txt'): 操作原文件的扩展属性\n");
    printf("  llistxattr('test_symlink'): 操作符号链接本身的扩展属性\n");
    
    // 演示错误处理
    printf("\n3. 错误处理演示:\n");
    
    // 尝试获取不存在文件的扩展属性
    ssize_t result = llistxattr("nonexistent_link", NULL, 0);
    if (result == -1) {
        printf("获取不存在文件的属性列表: %s (预期行为)\n", strerror(errno));
    }
    
    // 尝试获取普通文件(非符号链接)的扩展属性
    result = llistxattr("test_file.txt", NULL, 0);
    if (result != -1) {
        printf("获取普通文件属性列表大小: %zd 字节\n", result);
    } else {
        printf("获取普通文件属性列表失败: %s\n", strerror(errno));
    }
    
    // 演示缓冲区大小处理
    printf("\n4. 缓冲区大小处理演示:\n");
    
    // 使用过小的缓冲区
    char small_buffer[10];
    ssize_t small_result = llistxattr("test_symlink", small_buffer, sizeof(small_buffer));
    if (small_result == -1) {
        if (errno == ERANGE) {
            printf("缓冲区太小 (预期行为): %s\n", strerror(errno));
        } else {
            printf("其他错误: %s\n", strerror(errno));
        }
    } else {
        printf("意外成功,返回大小: %zd\n", small_result);
    }
    
    // 清理测试环境
    printf("\n5. 清理测试环境:\n");
    
    // 删除扩展属性
    const char* link_attrs[] = {"user.link_comment", "user.link_target"};
    for (int i = 0; i < 2; i++) {
        if (lremovexattr("test_symlink", link_attrs[i]) == 0) {
            printf("删除符号链接属性: %s\n", link_attrs[i]);
        }
    }
    
    const char* file_attrs[] = {"user.comment", "user.author", "trusted.security_label"};
    for (int i = 0; i < 3; i++) {
        if (removexattr("test_file.txt", file_attrs[i]) == 0) {
            printf("删除文件属性: %s\n", file_attrs[i]);
        }
    }
    
    // 删除测试文件
    unlink("test_symlink");
    unlink("test_file.txt");
    printf("清理完成\n");
    
    printf("\n=== 基础llistxattr演示完成 ===\n");
    
    return 0;
}

示例2:符号链接扩展属性详细管理 Link to heading

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <attr/xattr.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>

// 扩展属性信息结构
typedef struct {
    char name[256];
    char value[1024];
    size_t value_size;
    int exists;
} xattr_info_t;

#define MAX_XATTRS 64

// 获取扩展属性详细信息
int get_xattr_details(const char* filename, int follow_symlink) {
    printf("获取文件 '%s' 的扩展属性详细信息 (%s符号链接):\n", 
           filename, follow_symlink ? "跟随" : "不跟随");
    
    // 首先获取属性列表大小
    ssize_t list_size;
    if (follow_symlink) {
        list_size = listxattr(filename, NULL, 0);
    } else {
        list_size = llistxattr(filename, NULL, 0);
    }
    
    if (list_size == -1) {
        if (errno == ENOTSUP) {
            printf("  文件系统不支持扩展属性\n");
            return 0;
        } else if (errno == ENODATA) {
            printf("  文件没有扩展属性\n");
            return 0;
        } else {
            printf("  获取属性列表大小失败: %s\n", strerror(errno));
            return -1;
        }
    }
    
    if (list_size == 0) {
        printf("  文件没有扩展属性\n");
        return 0;
    }
    
    // 分配缓冲区获取属性列表
    char* list = malloc(list_size);
    if (!list) {
        printf("  内存分配失败\n");
        return -1;
    }
    
    if (follow_symlink) {
        list_size = listxattr(filename, list, list_size);
    } else {
        list_size = llistxattr(filename, list, list_size);
    }
    
    if (list_size == -1) {
        printf("  获取属性列表失败: %s\n", strerror(errno));
        free(list);
        return -1;
    }
    
    // 解析并获取每个属性的详细信息
    const char* ptr = list;
    int attr_count = 0;
    
    while (ptr < list + list_size && attr_count < MAX_XATTRS) {
        size_t attr_len = strlen(ptr);
        if (attr_len > 0) {
            char* attr_name = (char*)ptr;
            
            // 获取属性值大小
            ssize_t value_size;
            if (follow_symlink) {
                value_size = getxattr(filename, attr_name, NULL, 0);
            } else {
                value_size = lgetxattr(filename, attr_name, NULL, 0);
            }
            
            if (value_size != -1) {
                printf("  属性 %d:\n", attr_count + 1);
                printf("    名称: %s\n", attr_name);
                printf("    值大小: %zd 字节\n", value_size);
                
                // 获取属性值
                if (value_size > 0) {
                    char* value = malloc(value_size + 1);
                    if (value) {
                        ssize_t result;
                        if (follow_symlink) {
                            result = getxattr(filename, attr_name, value, value_size);
                        } else {
                            result = lgetxattr(filename, attr_name, value, value_size);
                        }
                        
                        if (result != -1) {
                            value[result] = '\0';  // 确保字符串结尾
                            
                            // 尝试以字符串形式显示
                            int is_printable = 1;
                            for (int i = 0; i < result; i++) {
                                if (value[i] < 32 || value[i] > 126) {
                                    if (value[i] != '\n' && value[i] != '\t') {
                                        is_printable = 0;
                                        break;
                                    }
                                }
                            }
                            
                            if (is_printable) {
                                printf("    值: %s\n", value);
                            } else {
                                printf("    值 (十六进制): ");
                                for (int i = 0; i < result && i < 32; i++) {
                                    printf("%02x ", (unsigned char)value[i]);
                                }
                                if (result > 32) printf("...");
                                printf("\n");
                            }
                        } else {
                            printf("    获取值失败: %s\n", strerror(errno));
                        }
                        free(value);
                    }
                } else {
                    printf("    值: (空)\n");
                }
            } else {
                printf("  属性: %s (获取信息失败: %s)\n", attr_name, strerror(errno));
            }
            
            attr_count++;
            ptr += attr_len + 1;
        } else {
            ptr++;
        }
    }
    
    printf("  总计: %d 个扩展属性\n\n", attr_count);
    free(list);
    
    return attr_count;
}

// 创建复杂的符号链接测试环境
int create_complex_symlink_environment() {
    printf("创建复杂的符号链接测试环境...\n");
    
    // 创建多层目录结构
    if (mkdir("xattr_test", 0755) == -1 && errno != EEXIST) {
        perror("创建测试目录失败");
        return -1;
    }
    
    if (mkdir("xattr_test/subdir", 0755) == -1 && errno != EEXIST) {
        perror("创建子目录失败");
        return -1;
    }
    
    // 创建目标文件
    char target_file[] = "xattr_test/subdir/target_file.txt";
    int fd = open(target_file, O_CREAT | O_WRONLY | O_TRUNC, 0644);
    if (fd != -1) {
        const char* content = "目标文件内容\n用于测试符号链接扩展属性\n";
        write(fd, content, strlen(content));
        close(fd);
        printf("创建目标文件: %s\n", target_file);
    }
    
    // 创建不同类型的符号链接
    struct {
        const char* link_name;
        const char* target;
        const char* description;
    } symlinks[] = {
        {"xattr_test/link_to_file", "subdir/target_file.txt", "相对路径符号链接"},
        {"xattr_test/absolute_link", "/tmp/xattr_test/subdir/target_file.txt", "绝对路径符号链接"},
        {"xattr_test/broken_link", "nonexistent_file.txt", "损坏的符号链接"},
        {"xattr_test/self_link", "self_link", "自引用符号链接"}
    };
    
    for (int i = 0; i < 4; i++) {
        // 特殊处理自引用链接
        if (i == 3) {
            // 创建自引用需要特殊处理
            continue;
        }
        
        if (symlink(symlinks[i].target, symlinks[i].link_name) == 0) {
            printf("创建%s: %s -> %s\n", 
                   symlinks[i].description, symlinks[i].link_name, symlinks[i].target);
        }
    }
    
    // 为不同对象设置不同类型的扩展属性
    printf("\n设置扩展属性:\n");
    
    // 为目标文件设置属性
    struct {
        const char* file;
        const char* attr;
        const char* value;
        int use_lxattr;  // 1表示使用l*函数(符号链接),0表示普通函数
    } xattrs[] = {
        {target_file, "user.file_owner", "system_admin", 0},
        {target_file, "user.file_version", "1.0", 0},
        {target_file, "security.selinux", "unconfined_u:object_r:user_home_t:s0", 0},
        {"xattr_test/link_to_file", "user.link_description", "指向子目录文件的链接", 1},
        {"xattr_test/link_to_file", "user.link_created", "2023-01-01", 1},
        {"xattr_test/absolute_link", "user.absolute_link_info", "绝对路径链接", 1},
        {"xattr_test/broken_link", "user.broken_link_note", "这是一个损坏的链接", 1}
    };
    
    for (int i = 0; i < 7; i++) {
        int result;
        if (xattrs[i].use_lxattr) {
            result = lsetxattr(xattrs[i].file, xattrs[i].attr, xattrs[i].value, 
                              strlen(xattrs[i].value), 0);
        } else {
            result = setxattr(xattrs[i].file, xattrs[i].attr, xattrs[i].value, 
                             strlen(xattrs[i].value), 0);
        }
        
        if (result == 0) {
            printf("  为%s设置 %s = %s\n", 
                   xattrs[i].file, xattrs[i].attr, xattrs[i].value);
        } else {
            printf("  为%s设置 %s 失败: %s\n", 
                   xattrs[i].file, xattrs[i].attr, strerror(errno));
        }
    }
    
    return 0;
}

int main() {
    printf("=== 符号链接扩展属性详细管理示例 ===\n");
    
    // 创建测试环境
    if (create_complex_symlink_environment() == -1) {
        exit(EXIT_FAILURE);
    }
    
    // 分析不同符号链接的扩展属性
    printf("\n1. 分析符号链接扩展属性:\n");
    
    const char* test_links[] = {
        "xattr_test/link_to_file",
        "xattr_test/absolute_link",
        "xattr_test/broken_link"
    };
    
    const char* descriptions[] = {
        "相对路径符号链接",
        "绝对路径符号链接",
        "损坏的符号链接"
    };
    
    for (int i = 0; i < 3; i++) {
        printf("\n--- %s: %s ---\n", descriptions[i], test_links[i]);
        
        // 检查链接是否存在
        struct stat link_stat;
        if (lstat(test_links[i], &link_stat) == -1) {
            printf("  无法获取链接状态: %s\n", strerror(errno));
            continue;
        }
        
        printf("  链接状态: %s\n", S_ISLNK(link_stat.st_mode) ? "符号链接" : "其他");
        
        // 获取符号链接本身的扩展属性(不跟随)
        printf("  符号链接本身的扩展属性:\n");
        get_xattr_details(test_links[i], 0);  // 0 = 不跟随符号链接
        
        // 获取目标文件的扩展属性(跟随)
        printf("  目标文件的扩展属性:\n");
        get_xattr_details(test_links[i], 1);  // 1 = 跟随符号链接
    }
    
    // 分析目标文件的扩展属性
    printf("\n2. 分析目标文件扩展属性:\n");
    get_xattr_details("xattr_test/subdir/target_file.txt", 1);
    
    // 演示属性名称空间
    printf("\n3. 扩展属性名称空间演示:\n");
    
    const char* namespaces[] = {
        "user.", "trusted.", "security.", "system."
    };
    
    const char* namespace_desc[] = {
        "用户属性", "可信属性", "安全属性", "系统属性"
    };
    
    printf("扩展属性名称空间:\n");
    for (int i = 0; i < 4; i++) {
        printf("  %s - %s\n", namespaces[i], namespace_desc[i]);
    }
    
    // 检查当前文件系统支持的属性
    printf("\n  当前环境中的属性示例:\n");
    ssize_t list_size = llistxattr("xattr_test/link_to_file", NULL, 0);
    if (list_size > 0) {
        char* list = malloc(list_size);
        if (list) {
            if (llistxattr("xattr_test/link_to_file", list, list_size) > 0) {
                const char* ptr = list;
                while (ptr < list + list_size) {
                    size_t attr_len = strlen(ptr);
                    if (attr_len > 0) {
                        printf("    %s", ptr);
                        if (strncmp(ptr, "user.", 5) == 0) {
                            printf(" (用户属性)");
                        } else if (strncmp(ptr, "security.", 9) == 0) {
                            printf(" (安全属性)");
                        } else if (strncmp(ptr, "trusted.", 8) == 0) {
                            printf(" (可信属性)");
                        } else if (strncmp(ptr, "system.", 7) == 0) {
                            printf(" (系统属性)");
                        }
                        printf("\n");
                        ptr += attr_len + 1;
                    } else {
                        ptr++;
                    }
                }
            }
            free(list);
        }
    }
    
    // 演示错误处理和边界情况
    printf("\n4. 错误处理和边界情况演示:\n");
    
    // 测试不存在的文件
    printf("测试不存在的文件:\n");
    ssize_t result = llistxattr("nonexistent_file", NULL, 0);
    if (result == -1) {
        printf("  %s\n", strerror(errno));
    }
    
    // 测试普通文件(非符号链接)
    printf("测试普通文件:\n");
    result = llistxattr("xattr_test/subdir/target_file.txt", NULL, 0);
    if (result != -1) {
        printf("  普通文件也可以使用llistxattr,大小: %zd\n", result);
    } else {
        printf("  %s\n", strerror(errno));
    }
    
    // 测试空路径
    printf("测试空路径:\n");
    result = llistxattr("", NULL, 0);
    if (result == -1) {
        printf("  %s\n", strerror(errno));
    }
    
    // 测试权限问题
    printf("权限检查演示:\n");
    // 这需要创建一个其他用户拥有的文件来完整演示
    
    // 清理测试环境
    printf("\n5. 清理测试环境:\n");
    
    // 删除扩展属性
    struct {
        const char* file;
        const char* attr;
        int use_lxattr;
    } remove_attrs[] = {
        {"xattr_test/link_to_file", "user.link_description", 1},
        {"xattr_test/link_to_file", "user.link_created", 1},
        {"xattr_test/absolute_link", "user.absolute_link_info", 1},
        {"xattr_test/broken_link", "user.broken_link_note", 1},
        {"xattr_test/subdir/target_file.txt", "user.file_owner", 0},
        {"xattr_test/subdir/target_file.txt", "user.file_version", 0},
        {"xattr_test/subdir/target_file.txt", "security.selinux", 0}
    };
    
    for (int i = 0; i < 7; i++) {
        int result;
        if (remove_attrs[i].use_lxattr) {
            result = lremovexattr(remove_attrs[i].file, remove_attrs[i].attr);
        } else {
            result = removexattr(remove_attrs[i].file, remove_attrs[i].attr);
        }
        
        if (result == 0) {
            printf("删除%s的属性: %s\n", remove_attrs[i].file, remove_attrs[i].attr);
        } else {
            printf("删除%s的属性 %s 失败: %s\n", 
                   remove_attrs[i].file, remove_attrs[i].attr, strerror(errno));
        }
    }
    
    // 删除测试文件
    unlink("xattr_test/link_to_file");
    unlink("xattr_test/absolute_link");
    unlink("xattr_test/broken_link");
    unlink("xattr_test/subdir/target_file.txt");
    rmdir("xattr_test/subdir");
    rmdir("xattr_test");
    
    printf("清理完成\n");
    
    printf("\n=== 符号链接扩展属性详细管理演示完成 ===\n");
    
    return 0;
}

示例3:批量符号链接属性管理和统计 Link to heading

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <attr/xattr.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <dirent.h>
#include <time.h>

#define MAX_SYMLINKS 1000
#define MAX_XATTRS_PER_FILE 64

// 符号链接属性统计信息
typedef struct {
    char path[512];
    int is_symlink;
    int has_xattrs;
    int xattr_count;
    size_t total_xattr_size;
    char xattr_names[1024];  // 存储属性名称列表
    time_t scan_time;
} symlink_xattr_stats_t;

symlink_xattr_stats_t symlink_stats[MAX_SYMLINKS];
int total_symlinks = 0;

// 扫描目录中的符号链接及其扩展属性
int scan_symlinks_with_xattrs(const char* directory) {
    printf("扫描目录中的符号链接: %s\n", directory);
    
    DIR* dir = opendir(directory);
    if (dir == NULL) {
        printf("无法打开目录 %s: %s\n", directory, strerror(errno));
        return -1;
    }
    
    struct dirent* entry;
    while ((entry = readdir(dir)) != NULL && total_symlinks < MAX_SYMLINKS) {
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue;
        }
        
        // 构造完整路径
        char full_path[1024];
        snprintf(full_path, sizeof(full_path), "%s/%s", directory, entry->d_name);
        
        // 获取文件状态
        struct stat file_stat;
        if (lstat(full_path, &file_stat) == 0) {
            if (S_ISLNK(file_stat.st_mode)) {
                // 这是一个符号链接
                symlink_xattr_stats_t* stats = &symlink_stats[total_symlinks];
                strncpy(stats->path, full_path, sizeof(stats->path) - 1);
                stats->is_symlink = 1;
                stats->scan_time = time(NULL);
                
                // 获取扩展属性信息
                ssize_t list_size = llistxattr(full_path, NULL, 0);
                if (list_size > 0) {
                    stats->has_xattrs = 1;
                    stats->total_xattr_size = list_size;
                    
                    // 获取属性名称列表
                    char* list = malloc(list_size);
                    if (list) {
                        if (llistxattr(full_path, list, list_size) > 0) {
                            stats->xattr_count = 0;
                            stats->xattr_names[0] = '\0';
                            
                            // 解析属性名称
                            const char* ptr = list;
                            char* name_ptr = stats->xattr_names;
                            size_t names_len = 0;
                            
                            while (ptr < list + list_size && 
                                   stats->xattr_count < MAX_XATTRS_PER_FILE) {
                                size_t attr_len = strlen(ptr);
                                if (attr_len > 0) {
                                    if (names_len + attr_len + 2 < sizeof(stats->xattr_names)) {
                                        if (names_len > 0) {
                                            *name_ptr++ = ',';
                                            names_len++;
                                        }
                                        strcpy(name_ptr, ptr);
                                        name_ptr += attr_len;
                                        names_len += attr_len;
                                        stats->xattr_count++;
                                    }
                                    ptr += attr_len + 1;
                                } else {
                                    ptr++;
                                }
                            }
                        }
                        free(list);
                    }
                } else {
                    stats->has_xattrs = 0;
                    stats->xattr_count = 0;
                    stats->total_xattr_size = 0;
                    stats->xattr_names[0] = '\0';
                    
                    if (list_size == -1) {
                        if (errno != ENODATA && errno != ENOTSUP) {
                            printf("获取 %s 属性列表失败: %s\n", 
                                   full_path, strerror(errno));
                        }
                    }
                }
                
                total_symlinks++;
                printf("发现符号链接: %s (%d 个属性)\n", 
                       full_path, stats->xattr_count);
            } else if (S_ISDIR(file_stat.st_mode)) {
                // 递归扫描子目录
                scan_symlinks_with_xattrs(full_path);
            }
        }
    }
    
    closedir(dir);
    return 0;
}

// 显示符号链接属性统计
void show_symlink_xattr_statistics() {
    printf("\n=== 符号链接扩展属性统计 ===\n");
    
    if (total_symlinks == 0) {
        printf("未发现符号链接\n");
        return;
    }
    
    // 统计信息
    int symlinks_with_xattrs = 0;
    int total_xattrs = 0;
    size_t total_xattr_data = 0;
    
    for (int i = 0; i < total_symlinks; i++) {
        if (symlink_stats[i].has_xattrs) {
            symlinks_with_xattrs++;
            total_xattrs += symlink_stats[i].xattr_count;
            total_xattr_data += symlink_stats[i].total_xattr_size;
        }
    }
    
    printf("扫描结果:\n");
    printf("  总符号链接数: %d\n", total_symlinks);
    printf("  有扩展属性的符号链接: %d (%.1f%%)\n", 
           symlinks_with_xattrs, (double)symlinks_with_xattrs / total_symlinks * 100);
    printf("  扩展属性总数: %d\n", total_xattrs);
    printf("  扩展属性数据总大小: %zu 字节\n", total_xattr_data);
    
    if (symlinks_with_xattrs > 0) {
        printf("  平均每个有属性的链接: %.1f 个属性\n", 
               (double)total_xattrs / symlinks_with_xattrs);
    }
    
    // 显示详细信息(最多显示20个)
    printf("\n详细信息 (最多显示20个):\n");
    printf("%-40s %-6s %-8s %-10s %s\n", 
           "路径", "属性数", "大小(字节)", "有属性", "属性名称");
    printf("%-40s %-6s %-8s %-10s %s\n", 
           "----", "------", "----------", "------", "--------");
    
    int display_count = (total_symlinks > 20) ? 20 : total_symlinks;
    for (int i = 0; i < display_count; i++) {
        const symlink_xattr_stats_t* stats = &symlink_stats[i];
        printf("%-40s %-6d %-8zu %-10s %s\n",
               stats->path,
               stats->xattr_count,
               stats->total_xattr_size,
               stats->has_xattrs ? "是" : "否",
               stats->has_xattrs ? stats->xattr_names : "");
    }
    
    if (total_symlinks > 20) {
        printf("... 还有 %d 个符号链接\n", total_symlinks - 20);
    }
    
    printf("========================\n\n");
}

// 按属性名称空间分组统计
void show_namespace_statistics() {
    printf("=== 按属性名称空间统计 ===\n");
    
    int user_count = 0, security_count = 0, trusted_count = 0, system_count = 0;
    int other_count = 0;
    
    for (int i = 0; i < total_symlinks; i++) {
        if (symlink_stats[i].has_xattrs) {
            char* names = strdup(symlink_stats[i].xattr_names);
            if (names) {
                char* token = strtok(names, ",");
                while (token) {
                    if (strncmp(token, "user.", 5) == 0) {
                        user_count++;
                    } else if (strncmp(token, "security.", 9) == 0) {
                        security_count++;
                    } else if (strncmp(token, "trusted.", 8) == 0) {
                        trusted_count++;
                    } else if (strncmp(token, "system.", 7) == 0) {
                        system_count++;
                    } else {
                        other_count++;
                    }
                    token = strtok(NULL, ",");
                }
                free(names);
            }
        }
    }
    
    int total_namespaced = user_count + security_count + trusted_count + system_count + other_count;
    
    printf("属性名称空间分布:\n");
    printf("  user.* (用户属性): %d (%.1f%%)\n", 
           user_count, total_namespaced > 0 ? (double)user_count / total_namespaced * 100 : 0);
    printf("  security.* (安全属性): %d (%.1f%%)\n", 
           security_count, total_namespaced > 0 ? (double)security_count / total_namespaced * 100 : 0);
    printf("  trusted.* (可信属性): %d (%.1f%%)\n", 
           trusted_count, total_namespaced > 0 ? (double)trusted_count / total_namespaced * 100 : 0);
    printf("  system.* (系统属性): %d (%.1f%%)\n", 
           system_count, total_namespaced > 0 ? (double)system_count / total_namespaced * 100 : 0);
    printf("  其他属性: %d (%.1f%%)\n", 
           other_count, total_namespaced > 0 ? (double)other_count / total_namespaced * 100 : 0);
    printf("  总计: %d 个属性名称\n", total_namespaced);
    
    printf("========================\n\n");
}

// 创建批量测试环境
int create_batch_test_environment() {
    printf("创建批量测试环境...\n");
    
    // 创建测试目录结构
    const char* dirs[] = {
        "batch_xattr_test",
        "batch_xattr_test/dir1",
        "batch_xattr_test/dir2",
        "batch_xattr_test/dir3"
    };
    
    for (int i = 0; i < 4; i++) {
        if (mkdir(dirs[i], 0755) == -1 && errno != EEXIST) {
            printf("创建目录失败 %s: %s\n", dirs[i], strerror(errno));
        }
    }
    
    // 创建目标文件
    const char* target_files[] = {
        "batch_xattr_test/target1.txt",
        "batch_xattr_test/target2.txt",
        "batch_xattr_test/dir1/target3.txt"
    };
    
    for (int i = 0; i < 3; i++) {
        int fd = open(target_files[i], O_CREAT | O_WRONLY | O_TRUNC, 0644);
        if (fd != -1) {
            const char* content = "目标文件内容";
            write(fd, content, strlen(content));
            close(fd);
            printf("创建目标文件: %s\n", target_files[i]);
        }
    }
    
    // 创建大量符号链接
    printf("创建符号链接...\n");
    srand(time(NULL));
    
    for (int i = 0; i < 50; i++) {
        char link_name[256];
        char target_name[256];
        
        // 随机选择目标文件
        int target_index = rand() % 3;
        snprintf(target_name, sizeof(target_name), "%s", 
                 strrchr(target_files[target_index], '/') + 1);
        
        // 随机选择目录
        int dir_index = rand() % 4;
        snprintf(link_name, sizeof(link_name), "%s/link_%03d", 
                 dirs[dir_index], i);
        
        if (symlink(target_name, link_name) == 0) {
            // 为部分链接设置扩展属性
            if (i % 3 == 0) {  // 每3个链接设置属性
                char attr_name[64];
                char attr_value[128];
                
                snprintf(attr_name, sizeof(attr_name), "user.link_id_%03d", i);
                snprintf(attr_value, sizeof(attr_value), "链接编号%d", i);
                
                if (lsetxattr(link_name, attr_name, attr_value, 
                             strlen(attr_value), 0) == 0) {
                    printf("创建符号链接: %s (已设置属性)\n", link_name);
                } else {
                    printf("创建符号链接: %s (属性设置失败)\n", link_name);
                }
            } else {
                printf("创建符号链接: %s\n", link_name);
            }
        }
    }
    
    // 创建一些特殊类型的链接
    struct {
        const char* link_name;
        const char* target;
        const char* description;
    } special_links[] = {
        {"batch_xattr_test/broken_link", "nonexistent_target", "损坏链接"},
        {"batch_xattr_test/relative_link", "dir1/target3.txt", "相对路径链接"},
        {"batch_xattr_test/self_link", "self_link", "自引用链接"}
    };
    
    for (int i = 0; i < 3; i++) {
        if (i != 2) {  // 跳过自引用(需要特殊处理)
            if (symlink(special_links[i].target, special_links[i].link_name) == 0) {
                printf("创建%s: %s\n", special_links[i].description, special_links[i].link_name);
                
                // 为特殊链接设置属性
                char attr_name[64];
                snprintf(attr_name, sizeof(attr_name), "user.special_%d", i);
                
                if (lsetxattr(special_links[i].link_name, attr_name, 
                             special_links[i].description, 
                             strlen(special_links[i].description), 0) == 0) {
                    printf("  为特殊链接设置属性: %s\n", attr_name);
                }
            }
        }
    }
    
    return 0;
}

int main() {
    printf("=== 批量符号链接属性管理和统计示例 ===\n");
    
    // 创建批量测试环境
    if (create_batch_test_environment() == -1) {
        exit(EXIT_FAILURE);
    }
    
    // 扫描符号链接及其扩展属性
    printf("\n1. 扫描符号链接扩展属性:\n");
    total_symlinks = 0;
    if (scan_symlinks_with_xattrs("batch_xattr_test") == -1) {
        printf("扫描失败\n");
    } else {
        printf("扫描完成,发现 %d 个符号链接\n", total_symlinks);
    }
    
    // 显示统计信息
    show_symlink_xattr_statistics();
    
    // 显示名称空间统计
    show_namespace_statistics();
    
    // 演示属性操作
    printf("2. 演示属性操作:\n");
    
    // 查找有属性的符号链接
    printf("查找有扩展属性的符号链接:\n");
    int found_links = 0;
    for (int i = 0; i < total_symlinks && found_links < 5; i++) {
        if (symlink_stats[i].has_xattrs) {
            printf("  %s: %d 个属性\n", 
                   symlink_stats[i].path, symlink_stats[i].xattr_count);
            found_links++;
        }
    }
    
    // 演示属性详细信息获取
    if (total_symlinks > 0) {
        printf("\n获取第一个符号链接的详细属性信息:\n");
        if (symlink_stats[0].has_xattrs) {
            printf("链接: %s\n", symlink_stats[0].path);
            
            // 重新获取详细信息
            char* attr_names = strdup(symlink_stats[0].xattr_names);
            if (attr_names) {
                char* token = strtok(attr_names, ",");
                while (token && strlen(token) > 0) {
                    // 获取属性值
                    ssize_t value_size = lgetxattr(symlink_stats[0].path, token, NULL, 0);
                    if (value_size > 0) {
                        char* value = malloc(value_size + 1);
                        if (value) {
                            if (lgetxattr(symlink_stats[0].path, token, value, value_size) != -1) {
                                value[value_size] = '\0';
                                printf("  %s = %s\n", token, value);
                            }
                            free(value);
                        }
                    } else if (value_size == 0) {
                        printf("  %s = (空值)\n", token);
                    }
                    token = strtok(NULL, ",");
                }
                free(attr_names);
            }
        }
    }
    
    // 性能测试
    printf("\n3. 性能测试:\n");
    clock_t start_time = clock();
    
    // 重复扫描测试性能
    for (int i = 0; i < 10; i++) {
        total_symlinks = 0;
        scan_symlinks_with_xattrs("batch_xattr_test");
    }
    
    clock_t end_time = clock();
    double elapsed_time = ((double)(end_time - start_time)) / CLOCKS_PER_SEC;
    printf("10次扫描耗时: %.4f 秒\n", elapsed_time);
    printf("平均每次扫描: %.4f 秒\n", elapsed_time / 10);
    
    // 清理测试环境
    printf("\n4. 清理测试环境:\n");
    
    // 删除符号链接和属性
    DIR* dir = opendir("batch_xattr_test");
    if (dir) {
        struct dirent* entry;
        while ((entry = readdir(dir)) != NULL) {
            if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
                char full_path[512];
                snprintf(full_path, sizeof(full_path), "batch_xattr_test/%s", entry->d_name);
                
                // 如果是符号链接,删除其扩展属性
                struct stat file_stat;
                if (lstat(full_path, &file_stat) == 0 && S_ISLNK(file_stat.st_mode)) {
                    // 获取并删除扩展属性
                    ssize_t list_size = llistxattr(full_path, NULL, 0);
                    if (list_size > 0) {
                        char* list = malloc(list_size);
                        if (list) {
                            if (llistxattr(full_path, list, list_size) > 0) {
                                const char* ptr = list;
                                while (ptr < list + list_size) {
                                    size_t attr_len = strlen(ptr);
                                    if (attr_len > 0) {
                                        if (lremovexattr(full_path, ptr) == 0) {
                                            printf("删除属性: %s from %s\n", ptr, full_path);
                                        }
                                        ptr += attr_len + 1;
                                    } else {
                                        ptr++;
                                    }
                                }
                            }
                            free(list);
                        }
                    }
                }
                
                // 删除文件/链接
                if (unlink(full_path) == 0) {
                    printf("删除: %s\n", full_path);
                }
            }
        }
        closedir(dir);
    }
    
    // 删除目录
    rmdir("batch_xattr_test/dir1");
    rmdir("batch_xattr_test/dir2");
    rmdir("batch_xattr_test/dir3");
    rmdir("batch_xattr_test");
    
    printf("清理完成\n");
    
    printf("\n=== 批量符号链接属性管理演示完成 ===\n");
    
    return 0;
}

示例4:扩展属性安全和权限管理 Link to heading

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <attr/xattr.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>

// 安全属性操作记录
typedef struct {
    char operation[32];
    char filename[256];
    char attribute[128];
    uid_t user_id;
    gid_t group_id;
    time_t timestamp;
    int success;
    char error_message[128];
} xattr_audit_record_t;

#define MAX_AUDIT_RECORDS 1000
xattr_audit_record_t audit_records[MAX_AUDIT_RECORDS];
int audit_count = 0;

// 安全的llistxattr包装函数
ssize_t secure_llistxattr(const char* path, char* list, size_t size, 
                         const char* operation) {
    if (audit_count >= MAX_AUDIT_RECORDS) {
        fprintf(stderr, "审计记录缓冲区已满\n");
        return -1;
    }
    
    xattr_audit_record_t* record = &audit_records[audit_count];
    strncpy(record->operation, operation, sizeof(record->operation) - 1);
    strncpy(record->filename, path, sizeof(record->filename) - 1);
    record->attribute[0] = '\0';  // llistxattr不涉及特定属性
    record->user_id = getuid();
    record->group_id = getgid();
    record->timestamp = time(NULL);
    
    ssize_t result = llistxattr(path, list, size);
    record->success = (result != -1);
    
    if (result == -1) {
        strncpy(record->error_message, strerror(errno), sizeof(record->error_message) - 1);
    } else {
        record->error_message[0] = '\0';
    }
    
    audit_count++;
    return result;
}

// 安全的lgetxattr包装函数
ssize_t secure_lgetxattr(const char* path, const char* name, void* value, 
                        size_t size, const char* operation) {
    if (audit_count >= MAX_AUDIT_RECORDS) {
        fprintf(stderr, "审计记录缓冲区已满\n");
        return -1;
    }
    
    xattr_audit_record_t* record = &audit_records[audit_count];
    strncpy(record->operation, operation, sizeof(record->operation) - 1);
    strncpy(record->filename, path, sizeof(record->filename) - 1);
    strncpy(record->attribute, name, sizeof(record->attribute) - 1);
    record->user_id = getuid();
    record->group_id = getgid();
    record->timestamp = time(NULL);
    
    ssize_t result = lgetxattr(path, name, value, size);
    record->success = (result != -1);
    
    if (result == -1) {
        strncpy(record->error_message, strerror(errno), sizeof(record->error_message) - 1);
    } else {
        record->error_message[0] = '\0';
    }
    
    audit_count++;
    return result;
}

// 显示审计记录
void show_audit_records(int max_records) {
    printf("\n=== 扩展属性操作审计记录 ===\n");
    
    if (audit_count == 0) {
        printf("无审计记录\n");
        return;
    }
    
    int show_count = (max_records > 0 && max_records < audit_count) ? max_records : audit_count;
    
    printf("%-15s %-20s %-15s %-8s %-8s %-10s %s\n",
           "操作", "文件", "属性", "UID", "GID", "状态", "时间");
    printf("%-15s %-20s %-15s %-8s %-8s %-10s %s\n",
           "----", "----", "----", "---", "---", "----", "----");
    
    for (int i = 0; i < show_count; i++) {
        const xattr_audit_record_t* record = &audit_records[i];
        
        char time_str[32];
        strftime(time_str, sizeof(time_str), "%H:%M:%S", localtime(&record->timestamp));
        
        char short_filename[21];
        if (strlen(record->filename) > 20) {
            snprintf(short_filename, sizeof(short_filename), "...%s", 
                     record->filename + strlen(record->filename) - 17);
        } else {
            strncpy(short_filename, record->filename, sizeof(short_filename) - 1);
        }
        
        char short_attr[16];
        if (strlen(record->attribute) > 15) {
            snprintf(short_attr, sizeof(short_attr), "%.12s...", record->attribute);
        } else {
            strncpy(short_attr, record->attribute, sizeof(short_attr) - 1);
        }
        
        printf("%-15s %-20s %-15s %-8d %-8d %-10s %s\n",
               record->operation,
               short_filename,
               short_attr[0] ? short_attr : "N/A",
               (int)record->user_id,
               (int)record->group_id,
               record->success ? "成功" : "失败",
               time_str);
        
        if (!record->success && record->error_message[0]) {
            printf("  错误: %s\n", record->error_message);
        }
    }
    
    if (show_count < audit_count) {
        printf("... 还有 %d 条记录\n", audit_count - show_count);
    }
    
    printf("================================\n\n");
}

// 显示属性列表
void display_xattr_list_secure(const char* filename, const char* list, ssize_t list_size) {
    printf("文件 '%s' 的扩展属性列表:\n", filename);
    
    if (list_size <= 0) {
        if (list_size == 0) {
            printf("  (无扩展属性)\n");
        } else {
            printf("  获取扩展属性列表失败: %s\n", strerror(errno));
        }
        return;
    }
    
    const char* ptr = list;
    int attr_count = 0;
    
    while (ptr < list + list_size) {
        size_t attr_len = strlen(ptr);
        if (attr_len > 0) {
            printf("  %s", ptr);
            
            // 根据属性名称空间显示权限信息
            if (strncmp(ptr, "user.", 5) == 0) {
                printf(" [用户属性]");
            } else if (strncmp(ptr, "security.", 9) == 0) {
                printf(" [安全属性 - 需要特殊权限]");
            } else if (strncmp(ptr, "trusted.", 8) == 0) {
                printf(" [可信属性 - 仅root可用]");
            } else if (strncmp(ptr, "system.", 7) == 0) {
                printf(" [系统属性 - 系统使用]");
            }
            
            printf("\n");
            attr_count++;
            ptr += attr_len + 1;
        } else {
            ptr++;
        }
    }
    
    printf("  总计: %d 个扩展属性\n\n", attr_count);
}

// 创建安全测试环境
int create_security_test_environment() {
    printf("创建安全测试环境...\n");
    
    // 创建测试文件
    int fd = open("security_test_file.txt", O_CREAT | O_WRONLY | O_TRUNC, 0644);
    if (fd != -1) {
        const char* content = "安全测试文件内容\n";
        write(fd, content, strlen(content));
        close(fd);
        printf("创建测试文件: security_test_file.txt\n");
    }
    
    // 创建符号链接
    if (symlink("security_test_file.txt", "security_test_link") == 0) {
        printf("创建符号链接: security_test_link\n");
    }
    
    // 设置不同权限级别的扩展属性
    printf("设置不同权限级别的扩展属性:\n");
    
    // 用户属性(普通用户可访问)
    if (setxattr("security_test_file.txt", "user.comment", "用户注释", 8, 0) == 0) {
        printf("  设置用户属性: user.comment\n");
    }
    
    if (lsetxattr("security_test_link", "user.link_info", "链接信息", 8, 0) == 0) {
        printf("  设置链接用户属性: user.link_info\n");
    }
    
    // 安全属性(需要适当权限)
    if (setxattr("security_test_file.txt", "security.test_label", "TEST_LABEL", 10, 0) == 0) {
        printf("  设置安全属性: security.test_label\n");
    }
    
    // 系统属性(系统使用)
    // 注意:某些系统属性可能需要特殊权限或内核支持
    
    return 0;
}

// 权限测试
void test_permissions() {
    printf("=== 权限测试 ===\n");
    
    uid_t current_uid = getuid();
    printf("当前用户ID: %d", (int)current_uid);
    
    struct passwd* pwd = getpwuid(current_uid);
    if (pwd) {
        printf(" (%s)", pwd->pw_name);
    }
    printf("\n");
    
    // 测试用户属性访问
    printf("1. 用户属性访问测试:\n");
    
    // 获取符号链接的用户属性列表
    ssize_t list_size = secure_llistxattr("security_test_link", NULL, 0, "llistxattr");
    if (list_size > 0) {
        char* list = malloc(list_size);
        if (list) {
            ssize_t result = secure_llistxattr("security_test_link", list, list_size, "llistxattr");
            if (result != -1) {
                display_xattr_list_secure("security_test_link", list, result);
            }
            free(list);
        }
    }
    
    // 测试特定属性访问
    printf("2. 特定属性访问测试:\n");
    
    char value[256];
    ssize_t value_size = secure_lgetxattr("security_test_link", "user.link_info", 
                                         value, sizeof(value) - 1, "lgetxattr");
    if (value_size > 0) {
        value[value_size] = '\0';
        printf("  user.link_info = %s\n", value);
    } else {
        printf("  无法获取 user.link_info: %s\n", strerror(errno));
    }
    
    // 测试安全属性访问
    printf("3. 安全属性访问测试:\n");
    
    value_size = secure_lgetxattr("security_test_link", "security.test_label", 
                                 value, sizeof(value) - 1, "lgetxattr");
    if (value_size > 0) {
        value[value_size] = '\0';
        printf("  security.test_label = %s\n", value);
    } else {
        printf("  无法获取 security.test_label: %s\n", strerror(errno));
    }
    
    // 测试不存在的属性
    printf("4. 不存在属性测试:\n");
    
    value_size = secure_lgetxattr("security_test_link", "user.nonexistent", 
                                 value, sizeof(value) - 1, "lgetxattr");
    if (value_size == -1) {
        printf("  user.nonexistent: %s (预期行为)\n", strerror(errno));
    }
}

// 显示当前系统支持的属性
void show_system_xattr_support() {
    printf("=== 系统扩展属性支持信息 ===\n");
    
    // 检查文件系统支持
    printf("文件系统扩展属性支持检查:\n");
    
    const char* test_files[] = {
        "security_test_file.txt",
        "/tmp",  // 临时目录
        "/"      // 根目录
    };
    
    for (int i = 0; i < 3; i++) {
        ssize_t result = llistxattr(test_files[i], NULL, 0);
        if (result != -1) {
            printf("  %s: 支持扩展属性", test_files[i]);
            if (result > 0) {
                printf(" (当前有属性)");
            } else {
                printf(" (支持但无属性)");
            }
            printf("\n");
        } else {
            if (errno == ENOTSUP) {
                printf("  %s: 不支持扩展属性\n", test_files[i]);
            } else {
                printf("  %s: 支持检查失败 (%s)\n", test_files[i], strerror(errno));
            }
        }
    }
    
    // 显示常见的属性名称空间
    printf("\n常见的扩展属性名称空间:\n");
    printf("  user.*     : 用户定义属性 (普通用户可访问)\n");
    printf("  security.* : 安全相关属性 (如SELinux标签)\n");
    printf("  trusted.*  : 可信属性 (通常仅root可访问)\n");
    printf("  system.*   : 系统属性 (内核和系统服务使用)\n");
    
    printf("============================\n\n");
}

int main() {
    printf("=== 扩展属性安全和权限管理示例 ===\n");
    
    // 创建安全测试环境
    if (create_security_test_environment() == -1) {
        exit(EXIT_FAILURE);
    }
    
    // 显示系统支持信息
    show_system_xattr_support();
    
    // 执行权限测试
    test_permissions();
    
    // 显示审计记录
    show_audit_records(20);
    
    // 统计审计信息
    printf("=== 审计统计 ===\n");
    int success_count = 0, failure_count = 0;
    for (int i = 0; i < audit_count; i++) {
        if (audit_records[i].success) {
            success_count++;
        } else {
            failure_count++;
        }
    }
    
    printf("操作统计:\n");
    printf("  总操作数: %d\n", audit_count);
    printf("  成功操作: %d (%.1f%%)\n", success_count, 
           audit_count > 0 ? (double)success_count / audit_count * 100 : 0);
    printf("  失败操作: %d (%.1f%%)\n", failure_count, 
           audit_count > 0 ? (double)failure_count / audit_count * 100 : 0);
    
    // 按操作类型统计
    printf("\n按操作类型统计:\n");
    int list_count = 0, get_count = 0;
    for (int i = 0; i < audit_count; i++) {
        if (strcmp(audit_records[i].operation, "llistxattr") == 0) {
            list_count++;
        } else if (strcmp(audit_records[i].operation, "lgetxattr") == 0) {
            get_count++;
        }
    }
    printf("  llistxattr 操作: %d\n", list_count);
    printf("  lgetxattr 操作: %d\n", get_count);
    printf("================\n\n");
    
    // 演示错误处理
    printf("=== 错误处理演示 ===\n");
    
    // 测试各种错误情况
    printf("测试错误处理:\n");
    
    // 不存在的文件
    ssize_t result = secure_llistxattr("nonexistent_file", NULL, 0, "llistxattr");
    if (result == -1) {
        printf("  不存在文件测试: %s (预期)\n", strerror(errno));
    }
    
    // 权限不足测试(需要适当设置文件权限)
    printf("  权限测试需要适当的文件权限设置来完整演示\n");
    
    // 缓冲区大小测试
    char small_buffer[5];
    result = secure_llistxattr("security_test_link", small_buffer, sizeof(small_buffer), "llistxattr");
    if (result == -1 && errno == ERANGE) {
        printf("  缓冲区大小测试: ERANGE (预期)\n");
    }
    
    printf("==================\n\n");
    
    // 清理测试环境
    printf("=== 清理测试环境 ===\n");
    
    // 删除扩展属性
    const char* attrs_to_remove[] = {
        "user.comment", "user.link_info", "security.test_label"
    };
    
    for (int i = 0; i < 3; i++) {
        if (removexattr("security_test_file.txt", attrs_to_remove[i]) == 0) {
            printf("删除文件属性: %s\n", attrs_to_remove[i]);
        }
        if (lremovexattr("security_test_link", attrs_to_remove[i]) == 0) {
            printf("删除链接属性: %s\n", attrs_to_remove[i]);
        }
    }
    
    // 删除测试文件
    unlink("security_test_link");
    unlink("security_test_file.txt");
    printf("删除测试文件\n");
    
    printf("清理完成\n");
    printf("==================\n");
    
    printf("\n=== 扩展属性安全和权限管理演示完成 ===\n");
    
    return 0;
}

编译和运行 Link to heading

# 编译示例1(需要安装attr开发包)
gcc -o llistxattr_example1 llistxattr_example1.c -lattr
./llistxattr_example1

# 编译示例2
gcc -o llistxattr_example2 llistxattr_example2.c -lattr
./llistxattr_example2

# 编译示例3
gcc -o llistxattr_example3 llistxattr_example3.c -lattr
./llistxattr_example3

# 编译示例4
gcc -o llistxattr_example4 llistxattr_example4.c -lattr
./llistxattr_example4

重要注意事项 Link to heading

  1. 文件系统支持: 不是所有文件系统都支持扩展属性
  2. 权限要求: 不同名称空间的属性有不同的访问权限要求
  3. 符号链接处理: llistxattr不跟随符号链接,操作链接本身
  4. 名称空间: 扩展属性有特定的名称空间规则
  5. 缓冲区管理: 需要正确处理缓冲区大小和内存分配
  6. 错误处理: 必须检查返回值并处理各种错误情况
  7. 安全考虑: 某些属性可能包含敏感信息

最佳实践 Link to heading

  1. 安全包装: 使用安全包装函数进行审计和错误处理
  2. 权限检查: 在操作前检查必要的权限
  3. 缓冲区处理: 正确处理缓冲区大小和内存分配
  4. 名称空间验证: 验证属性名称空间的合法性
  5. 错误日志: 记录所有扩展属性操作的详细信息
  6. 资源清理: 及时释放分配的内存资源
  7. 性能考虑: 批量操作时考虑性能影响

通过这些示例,你可以理解llistxattr在符号链接扩展属性管理方面的强大功能,它为Linux系统提供了灵活的元数据管理能力,特别适用于安全系统、文件管理工具和系统监控应用。