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
相关推荐
wljy11 天前
二、进制状态转换
linux·运维·服务器·c语言·c++
week@eight1 天前
Linux - Doris
linux·运维·数据库·mysql
平行云1 天前
实时云渲染预启动技术解析:UE数字孪生应用的延迟优化机制(二)
linux·unity·ue5·webgl·实时云渲染·云桌面·像素流
看到代码头都是大的1 天前
CentOS环境下手动升级openssl、openssh
linux·运维·centos
浮生若城1 天前
Linux——Ext系列文件系统
linux·运维·服务器
枳实-叶1 天前
【Linux驱动开发】第16天:按键中断完整实战
linux·运维·驱动开发
杨云龙UP1 天前
Oracle Recycle Bin 回收站详解:DROP TABLE 后还能找回吗?
linux·运维·数据库·sql·mysql·oracle
又熟了1 天前
乌班图Ubuntu安装
linux·运维·ubuntu
Cat_Rocky1 天前
Linux-ansible之Playbook简单应用
linux·网络·ansible
Do_GH1 天前
【Linux】09.WSL+SVN部署操作说明
linux·运维·svn