TLPI 第17章 练习:Access Control Lists

笔记和练习博客总目录见:开始读TLPI。

练习 17-1.

编写一个程序,显示对应于特定用户或组的 ACL 条目的权限。程序应接受两个命令行参数。第一个参数是字母 u 或 g,用于指示第二个参数标识的是用户还是组。(可以使用第 159 页列表 8-1 中定义的函数,允许第二个命令行参数以数字或名称的形式指定。)如果对应于给定用户或组的 ACL 条目属于组类,那么程序还应显示在 ACL 条目被 ACL 掩码条目修改后将适用的权限。


列表 8-1 中定义的函数是指users_groups/ugid_functions.c。

编译时要指定 -lacl。

代码的框架参考了acl/acl_view.c。

代码如下:

c 复制代码
// ex17-1.c
#include <acl/libacl.h>
#include <sys/acl.h>
#include <stdlib.h>
#include "ugid_functions.h"
#include "tlpi_hdr.h"

int
main(int argc, char *argv[])
{
    acl_t acl;
    acl_type_t type;
    acl_entry_t entry;
    acl_tag_t tag;
    uid_t *uidp;
    gid_t *gidp;
    acl_permset_t permset;
    char *name, *pathname;
    int entryId, permVal;
    uid_t u = -1;
    gid_t g = -1;
    int id;
    int match;

    if (argc < 4 || strcmp(argv[1], "--help") == 0)
        usageErr("%s pathname {u|g} id\n", argv[0]);

    pathname = argv[1];

    id = atoi(argv[3]);
    switch(argv[2][0]) {
    case 'u':
        if(id == 0)
            u = userIdFromName(argv[3]);
        else
            u = (uid_t)id;

        if (u == (uid_t)-1 || userNameFromId(u) == NULL)
            usageErr("%s is not a valid user id/name\n", argv[3]);

        break;
    case 'g':
        if(id == 0)
            g = groupIdFromName(argv[3]);
        else
            g = (gid_t)id;

        if (g == (gid_t)-1 || groupNameFromId(g) == NULL)
            usageErr("%s is not a valid group id/name\n", argv[3]);
        break;

    default:
        usageErr("%s pathname {u|g} {idname}\n", argv[0]);
        break;
    }


    type = ACL_TYPE_ACCESS;

    acl = acl_get_file(pathname, type);
    if (acl == NULL)
        errExit("acl_get_file");

    /* Walk through each entry in this ACL */

    for (entryId = ACL_FIRST_ENTRY; ; entryId = ACL_NEXT_ENTRY) {

        match = 0;
        if (acl_get_entry(acl, entryId, &entry) != 1)
            break;                      /* Exit on error or no more entries */

        /* Retrieve and display tag type */

        if (acl_get_tag_type(entry, &tag) == -1)
            errExit("acl_get_tag_type");

        if (u != (uid_t)-1 && tag == ACL_USER) {

            uidp = acl_get_qualifier(entry);
            if (uidp == NULL)
                errExit("acl_get_qualifier");

            if( u == *uidp) {
                match = 1;
                printf("%-12s", "user");
                name = userNameFromId(*uidp);
                if (name == NULL)
                    printf("%-8d ", *uidp);
                else
                    printf("%-8s ", name);
            }
            if (acl_free(uidp) == -1)
                errExit("acl_free");
        } else if (g != (gid_t)-1 && tag == ACL_GROUP) {

            gidp = acl_get_qualifier(entry);
            if (gidp == NULL)
                errExit("acl_get_qualifier");

            if( g == *gidp) {
                match = 1;
                printf("%-12s", "group");
                name = groupNameFromId(*gidp);
                if (name == NULL)
                    printf("%-8d ", *gidp);
                else
                    printf("%-8s ", name);

            }
            if (acl_free(gidp) == -1)
                errExit("acl_free");
        } else
            continue;


        if(match) {
            if (acl_get_permset(entry, &permset) == -1)
                errExit("acl_get_permset");

            permVal = acl_get_perm(permset, ACL_READ);
            if (permVal == -1)
                errExit("acl_get_perm - ACL_READ");
            printf("%c", (permVal == 1) ? 'r' : '-');
            permVal = acl_get_perm(permset, ACL_WRITE);
            if (permVal == -1)
                errExit("acl_get_perm - ACL_WRITE");
            printf("%c", (permVal == 1) ? 'w' : '-');
            permVal = acl_get_perm(permset, ACL_EXECUTE);
            if (permVal == -1)
                errExit("acl_get_perm - ACL_EXECUTE");
            printf("%c", (permVal == 1) ? 'x' : '-');
        }

        printf("\n");
    }

    if (acl_free(acl) == -1)
        errExit("acl_free");

    exit(EXIT_SUCCESS);
}

创建测试文件:

bash 复制代码
touch tfile
sudo useradd paulh
sudo groupadd teach
setfacl -m u:paulh:rx,g:teach:x tfile

其ACL如下:

bash 复制代码
$ getfacl --omit-header tfile
user::rw-
user:paulh:r-x
group::r--
group:teach:--x
mask::r-x
other::r--

验证如下:

bash 复制代码
$ ./ex17-1 tfile u paulh
user        paulh    r-x
$ ./ex17-1 tfile g teach
group       teach    --x
相关推荐
坤坤子吖10 小时前
Linux网络编程:TCP 粘包与半包问题,如何正确处理 TCP 流式数据?
linux·服务器·网络·笔记·网络协议·学习
AI_Gump10 小时前
Harness篇|DeepSeek Harness 上手机:五条安卓移植路线与 App 内 Linux 拆解
android·linux·人工智能·智能手机·deepseek
星恒随风12 小时前
MySQL 从零入门(六):复合查询详解——多表查询、自连接、子查询与 UNION
linux·服务器·数据库·mysql
少司府12 小时前
嵌入式入门篇(二):初识STM32F103ZET6
linux·python·stm32·单片机·嵌入式硬件·mcu·嵌入式软件
无足鸟ICT12 小时前
【RHCA+】IO调度算法
linux·服务器
wacsii13 小时前
【Linux进程(四)】命令行参数与环境变量
linux·服务器
无奈笑天下13 小时前
银河麒麟上lsblk命令教程详解
linux·运维·服务器·数据库
科研邪修法14 小时前
培训PDF保护配置:把需求转换成可验收权限
linux·服务器·网络
Felven15 小时前
中科驭数100G网卡RDMA性能测试
linux·rdma·中科驭数·100g网卡
雪落漂泊17 小时前
Liunux进程(七):程序控制篇(中)
linux·运维·windows