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
相关推荐
A小辣椒15 小时前
TShark:Wireshark CLI 功能
linux
A小辣椒19 小时前
TShark:基础知识
linux
AlfredZhao21 小时前
OCI 明明分配了 200G 系统盘,为什么 df 只看到 30G?
linux·oci
AlfredZhao1 天前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户9718356334662 天前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪2 天前
linux 拷贝文件或目录到指定的位置
linux
摇滚侠2 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
bush42 天前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行5202 天前
Linux 11 动态监控指令top
linux
不会C语言的男孩3 天前
Linux 系统编程 · 第 8 章:进程基础
linux·c语言