ext2文件系统源代码之acl.c

本文详细解析了ext2文件系统源代码中的acl.c文件,该文件主要涉及ACL权限控制的实现。文章首先介绍了ACL的posix结构体和ext2实现,接着详细解释了`ext2_acl_from_disk`和`ext2_acl_to_disk`两个关键函数,用于在内存和硬盘格式之间转换ACL。最后,文章涵盖了从inode获取和设置ACL的函数,以及如何将ACL与进程umask进行比较和处理。
摘要由CSDN通过智能技术生成
今天继续看ext2源代码的acl.c文件,这个文件代码有点多是一些acl权限控制的实现,有点麻烦-_-,代码注释都是中文的,大家有问题随时欢迎骚扰哦
在分析之前,为了不让大家看代码的时候感到有疑惑,给大家科普一下acl结构体的posix实现和ext2实现。acl的基本我上节应该都说过了,然后我们来看一下posix实现,定义如下
struct posix_acl {
	/*引用计数*/
	atomic_t		a_refcount;
	/*内部有几个acl项*/
	unsigned int		a_count;
	/*实际数据区*/
	struct posix_acl_entry	a_entries[0];
};
/*acl项结构体*/
struct posix_acl_entry {
	short			e_tag;
	unsigned short		e_perm;
	unsigned int		e_id;
};

看到这里大家可能会感到疑惑定义a_entries[0]是什么意思,这不和没定义一样吗?错了,大不一样!这里的实现非常巧妙,在linux内核里,posix结构是开头是struct posix_acl,后边的控制项有几个,就连这几个posix_acl_entry结构体,而这个a_entries[0]明明不占用空间,却方便了访问后边的acl项,如果想访问第一个,就直接p->a_entries[0]就可以了,因为后边的acl项在内存上是连续的,至少虚拟内存上是这样的。看到这里我真的是赞不绝口,为这些内核coder深深折服啊。
而ext2的acl实现我们上节就已经探讨过了,然后就可以直接看acl.c啦

/*
 * linux/fs/ext2/acl.c
 *
 * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
 */


#include <linux/capability.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include "ext2.h"
#include "xattr.h"
#include "acl.h"


/*把硬盘上的ext2的acl数据转成内存上的posix标准的acl数据
ext2文件系统的acl格式数据是开头是一个ext2_acl_header结构体的ext2头部,然后接下来是ext2_acl_entry_short或者是ext2_acl_entry结构体的acl实体
内存存储的posix标准的acl数据是开头是一个posix_acl结构体,然后随后就是count个posix_acl_entry结构体
*/
static struct posix_acl *
ext2_acl_from_disk(const void *value, size_t size)
{
	const char *end = (char *)value + size;
	int n, count;
	struct posix_acl *acl;
	/*如果参数是NULL,直接返回NULL*/
	if (!value)
		return NULL;
	/*如果大小小于ext2_acl_header大小,说明有错误*/
	if (size < sizeof(ext2_acl_header))
		 return ERR_PTR(-EINVAL);
	/*如果数据合法的话,开头肯定是ext2_acl_header,直接转化为ext2_acl_header指针,检验当前版本是否一致*/
	if (((ext2_acl_header *)value)->a_version !=
	    cpu_to_le32(EXT2_ACL_VERSION))
		return ERR_PTR(-EINVAL);
	/*value指向头部后边的数据部分*/
	value = (char *)value + sizeof(ext2_acl_header);
	/*这个函数之前讲过,根据acl数据大小返回数据项数目*/
	count = ext2_acl_count(size);
	/*返回参数检查*/
	if (count < 0)
		return ERR_PTR(-EINVAL);
	if (count == 0)
		return NULL;
	/*根据返回的 项数,分配一定的posix标准结构体内存,这个函数是在fs/posix_acl.c实现,实现很简单*/
	acl = posix_acl_alloc(count, GFP_KERNEL);
	if (!acl)
		return ERR_PTR(-ENOMEM);
	/*大循环来啦,对于每一项赋值*/
	for (n=0; n < count; n++) {
		/*entry指针指向第n项的ext2格式数据*/
		ext2_acl_entry *entry =
			(ext2_acl_entry *)value;
		/*检验边界是不是有问题,linux内核源代码真的是好严谨,至少我不会这么做*/
		if ((char *)value + sizeof(ext2_acl_entry_short) > end)
			goto fail;
		/*直接赋值,ext2文件系统是小端字节序,使用宏转化为cpu字节序
		另外我也觉得posix标准的struct posix_acl实现是一个很巧妙的实现,利用了c语言的开放性,大家可以看一下posix标准的linux源代码,真的很巧妙*/
		acl->a_entries[n].e_tag  = le16_to_cpu(entry->e_tag);
		acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm);
		/*根据e_tag的不同,e_id也不同,仅有两种e_tag的e_id不是空的,这是POSIX标准规定的*/
		switch(acl->a_entries[n].e_tag) {
			/*这四种情况,在ext2的实现上都是为空,但是在POSIX标准,都是ACL_UNDEFINED_ID*/
			case ACL_USER_OBJ:
			case ACL_GROUP_OBJ:
			case ACL_MASK:
			case ACL_OTHER:
				value = (char *)value +
					sizeof(ext2_acl_entry_sho
ext4文件系统的Inode结构体定义在内核源代码中的`include/linux/ext4_fs.h`文件中。 其结构体定义如下: ``` struct ext4_inode { __le16 i_mode; /* File mode */ __le16 i_uid; /* Low 16 bits of Owner Uid */ __le32 i_size_lo; /* Size in bytes */ __le32 i_atime; /* Access time */ __le32 i_ctime; /* Creation time */ __le32 i_mtime; /* Modification time */ __le32 i_dtime; /* Deletion Time */ __le16 i_gid; /* Low 16 bits of Group Id */ __le16 i_links_count; /* Links count */ __le32 i_blocks_lo; /* Blocks count */ __le32 i_flags; /* File flags */ union { struct { __le32 l_i_version; } linux1; struct { __u32 h_i_translator; } hurd1; struct { __u32 m_i_reserved1; } masix1; } osd1; /* OS dependent 1 */ __le32 i_block[EXT4_N_BLOCKS];/* Pointers to blocks */ __le32 i_generation; /* File version (for NFS) */ __le32 i_file_acl_lo; /* File ACL */ __le32 i_size_high; __le32 i_obso_faddr; /* Obsoleted fragment address */ union { struct { __le16 l_i_blocks_high; /* were l_i_reserved1 */ __le16 l_i_file_acl_high; __le16 l_i_uid_high; /* these 2 fields */ __le16 l_i_gid_high; /* were reserved2[0] */ __le16 l_i_checksum_lo;/* crc32c(uuid+inum+inode) LE */ __le16 l_i_reserved; } linux2; struct { __le16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */ __u16 h_i_mode_high; __u16 h_i_uid_high; __u16 h_i_gid_high; __u32 h_i_author; } hurd2; struct { __le16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */ __u16 m_i_file_acl_high; __u32 m_i_reserved2[1]; } masix2; } osd2; /* OS dependent 2 */ }; ``` 可以看到,`ext4_inode`结构体包含了文件的基本属性信息,如文件大小、文件类型、访问、修改和创建时间、文件所属用户和组、文件权限等。此外,还包含了指向文件内容的指针、文件所在的磁盘块号、文件版本号、文件ACL等信息。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值