笔记和练习博客总目录见:开始读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