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
相关推荐
hi_ro_a9 小时前
Linux基础开发工具详解
linux·运维·服务器
嵌入式阿蔡9 小时前
Linux_01:交叉编译与开发环境实战——从单片机跨到 Linux 的第一道坎
linux·运维·网络·单片机·嵌入式硬件·嵌入式实时数据库
Pocker_Spades_A9 小时前
终端里也能斗地主:Linux部署Ratel,从本地对战到公网联机
linux·运维·服务器
佳児素花痴╮10 小时前
C语言链接库
linux·运维·服务器
wWYy.10 小时前
Linux发送数据包的过程
linux·网络
小嵌同学11 小时前
Linux 内核中的 Per-CPU 机制详解
linux·运维·arm开发·嵌入式
Hello-FPGA11 小时前
嵌入式LINUX 设备 ip配置后怎么保存才能掉电不消失?
linux·运维·服务器
工业一体机老司机12 小时前
Linux工业一体机自启动服务配置:systemd服务单元编写与开机优化实战
java·linux·服务器
zhixingheyi_tian12 小时前
Linux 之 ssh
linux·服务器·ssh
小鱼仙官12 小时前
Ubuntu C++ NTP校时程序
linux·c++·ubuntu