第十五章 文件属性类的实现
根用户的权限也不能是无限大、必须考虑到保护用户的隐私!用户的文件内容、程序代码可设置为根用户也不能观看,只能是文件拥有者可以查看、修改。但根用户可以删除一切非根用户的文件、也可以查看用户的目录。所以,i_mode字符更改如下:
BU16 i_mode; // 描述文件的访问权限;文件的读、写、执行权限
// i_mode.15-13 ftype; 文件类型: 0-符号软连接文件,
// 1-硬连接文件,2-普通文件, 3-块设备文件,4-字符设备文件,
// 5-文件系统根目录型文件。
// i_mode.12 ACL; 文件访问权限是否由ACL文件描述。
// i_mode.11-0 FWQX; 文件访问权限: rwx-rwx-rwx-rwx,读、写、执行权限,分别是:
// 文件拥有者owner - 根root - 文件所属组 – 其它用户
文件的权限设置、必须是文件的拥有者才行!根用户也不行、除非文件拥有者在i_mode中、允许root对文件拥有读、写权限!
目录执行权限:允许搜索该目录、寻找一个特定文件。
目录读权限:允许列出目录中的所有文件的目录属性项。
删除、创建目录下的一个文件,必须对该目录有写、执行权限。
对文件内容的读、写、执行权限,取决于i_mode的12个权限位的设置。
i节点属性表为只读。
对文件的目录项属性表读,取决于i_mode的12个权限位的设置。部分变量的写、只能是文件拥有者。其中:inode索引i节点号(文件名字哈希值)、i_uid描述文件的拥有者标识、i_gid描述文件的用户组标识、i_count到本目录项的软连接计数器、i_ycount硬连接的计数器指针、i_size描述文件最后块或页的剩余行数或记录大小、i_blocks描述文件的数据块数或页数或记录数、i_fop文件名长度和操作方法表指针号、i_mblock描述文件的第一个连续数据块数或连续页数、i_mblockp指向第一个连续m个数据块或页或单位的首指针、i_ctime索引节点最后改变的时间,单位n秒、i_mtime文件最后修改时间标识,单位n秒、i_crtime文件的出生时间标识,单位nS、i_atime文件最后访问时间标识,单位n秒、共14项是只读属性。可改写的有:i_mode描述文件的访问权限,i_flags文件标志的i_flags.15-9的7个位,文件名字name;共3项。
i_uid、i_gid为登录时,在系统登录文件数据库中注册项中自动提取的、通常是靠前的、有效的项;i_uid是注册后、系统自动分配;除root可以注销该i_uid用户外、其它官都不行、但root也不能更改用户号;用户也可以申请注销其用户号、或组号。一个用户可以属于最多16个组,i_gid = 0xFFFF表示是无效组号;组长以上的官可以设置用户不属于该组,即在该组注销该用户;即是将其原来所属的组项i_gid_j(j
= 0-15)= 0xFFFF。每个小组最多64K个用户,每60个小组设一个大队长;每100个大队、设一个军团长。每个用户可以有多种身份,用户i_uid 号:root 0、系统服务进程和保留1-799、军团长800-810、元老811-999、大队长1000-1999、组长2000-65000。登录时,如果你有职称、系统会提示你用什么身份登录。官大一级压死人、上级可以撤销下级的职称ID;但军团长不能撤销元老,root则可以。组长有的权利、大队长以上也当然有;至于职称的福利、那是另外定义。每个用户最多可以注册拥有8个用户号,0xFFFFFFFF是空号。用户号、组号等等相关应用是属于用户数据库管理,说起来话长、以后再论。这样一来,进程的v节点(进程PCB)要改为8E(可执行文件v节点5E,用户、组号2E,task块1E);当用户登录时,系统从用户数据库读入2E的用户号、组号到用户shell进程v节点;用户再打开其它进程时,会自动继承这2E。
根用户权限,特权:
1、可以进行 目录下文件的删除、新建、搜索和列出目录的的文件项。
2、可以读进程属性v节点8E、或改写一部分变量。
3、可以注销用户。
其它权限、以i_mode字符的 rwx设置为准。
小组长以上的用户权限,特权:
可以注销下级的职称、或用户所属组号。
文件拥有者权限,对拥有的文件:可读、部分可写文件属性(文件i节点和对应目录项),如果是可执行文件、那可读、部分写进程属性v节点8E,可读本进程的方法表512E。对文件内容的读写,对目录下文件的删除、新建、搜索和列出目录的的文件项,以i_mode字符的 rwx设置为准。
文件组权限:如组rwx允许读、写,那只可读文件属性(文件i节点和对应目录项),可对文件内容读写。如果是可执行文件、那可读进程属性v节点8E(包含读寄存器组R0-R31),可读文件内容。
系统的各个类的属性表、和方法表都归类到一个内核类。文件属性类主要是针对文件属性、进程属性的读、和写;即是API方法fileget(),fileset()。在前面的第六章已经介绍了文件、进程的属性,这里就介绍实现方法。
文件、进程的属性都是属于系统管理的变量,用户程序只能调用系统方法来获取、或设置;这需要有相应的权限,才能进行。UINX、LINUX都是把这2个功能、搞成一大堆函数来实现、显得不清晰、和啰嗦;也势必使代码不精炼、和重复。
文件名指的是不带路径的文件名,而路径名(路径名变量pathname)的含义则较广泛,它既包括含路径的文件名,也包括单个文件名。文件、进程属性有:i节点2W、对应目录项4E、打开文件表项1E、文件v节点4E、进程v节点8E、路径名最大256E(4K字符)的属性、进程的方法表512E。常量字符串是以行为单位存放,不足一行的空余地方为0;const常量表通常编译到文件属性表中的D根对象后面。
静态变量只能是挂靠在某个Di对象号下,编译器也是给出对象号、相对偏移地址的结果,由程序装入时、安装相应对象号的真实地址、长度。不管是动态、静态变量你要读完整的属性表,都要给出足够大的容器来装属性数据;要不会被截断、或报错。前提是你必须有足够的权限,通常是根、或拥有者才行。
// 规定行的单位:E,页的单位是:Y,数据块的单位是:C,单元的单位是:D。
// 字符的单位:Z,字的单位:W,字节的单位:B,扇区的单位:S。
// 硬件规定:第0号数据块中的方法(实时CPU线路、和用户CPU线路,的内核方法库),
// 只能是第0、1号数据块中的方法可以调用;其它数据块中的方法最多能调用第1号
// 数据块中的方法(API库)及 >1的公开方法库。
CPU中有方法调用硬件监视器,CALL时、新的PPC就是目的地,而(PSP).7.W中的PPC就是源地的下一条指令,即返回点。硬件监视源地、目的地;目的地是0号数据块,那么需要源地不大于1号数据块。如果目的地是1号数据块API,那么许可。0、1号的方法是系统方法不可能去调用用户方法的,用户方法只能最多是调用1号数据块API库中的方法;不能调用内核方法;违者异常侍候。API中的方法可以调用0号数据块中的内核方法。这书编写的方法如果不注明是API,那隐含指是0号数据块的内核方法。
获取pid进程v节点指针方法:R28 = getpidvnode(,pid); 内核方法。
获取当前进程v节点指针方法:R28= getpidvnode(,B1L); B1L是只读寄存器。
入口:pid进程号送R1L寄存器,当前进程号是在B1L只读寄存器。
出口:R28 = 进程v节点指针。
占用:R28、4W
耗时:4ns
getpidvnode(,pid){// 传送参数1W、1ns
R28 = Process_vnode_tab; // R28指向进程v节点表首指针。
R28 = +R1L<<3; // R28指向相应pid的v节点项首指针。
RET
}
获取用户对象的指针方法:R29= getdxp(,对象名字); 内核方法。
入口:对象名字。
出口:R29 = 对象空间的首指针,长度在R30。
占用:R29-R30、8W
耗时:8ns
getdxp(,对象名字){// 对象的实际内存地址送PITR、并R1 = PITR; R2 =LENG; 5W、5ns。
R29 =R1; R30 = R2;// 用户想这样做是不行的、指令不在系统代码区域错。
RET
}
进程对文件的权限判断方法:R31H= accesspath(,pathname); 系统API方法。
类似linux的int access(const char * pathname,int mode); 但APO是返回文件的所有权限测试结果。
R31H; // 低8位错误代号、高8位权限、许可标志。
//R31H.15 FERR ;// 1、操作文件出错指示,0、否。
//R31H.14 root; // 1、是根用户,0、否。
//R31H.13 owner;// 1、是用户拥有者,0、否。
// R31H.12 grp; // 1、是组用户,0、否。
//R31H.11 Y_OK ;// 1、许可进程在目录中删除、或新建一个文件,0、否。
//R31H.10 X_OK ;// 1、许可进程执行该文件,0、否。
// R31H.9 WR_OK ;// 1、许可进程写文件内容,0、否。
//R31H.8 RD_OK ;// 1、许可进程读文件内容,0、否。
入口:路径名参数pathname。APO最多允许pathname 是4K字符,即256E,而路径的目录数最多允许1K个(包括/、平均4字符/个)。以“/”分割目录段,在APO中用硬件模块YJMK、一次10ns就可分割2K个字符,4K字符不就最多2次;耗时主要还是在对各个目录名的哈希运算。如果进程非根用户、那是须检查用户对路径上每一个目录的执行权限是否通过;否则还不到达最终的文件名、就给pass了;根用户就无需检查目录权限。而这一个过程是由API方法、checkpath()进行的,如果失败、就直接设标志后返回了。成功、R31H.15
=0。R31H.14 = 1、root是根用户,0、否。R31H.12 = 1、RDIR_OK许可进程读目录项,0、否。R31H.11 = 1、Y_OK许可进程在目录中删除、或新建一个文件,0、否。R31H.10-0 = 0。最后、返回文件名字哈希值到R0。
检查进程是否文件拥有者、或所属组;都是用硬件模块YJMK、一次约15ns就可得出。
出口:标志与错误码在R31H 寄存器。
占用:R0、R28、13W
耗时:13ns +
accesspath(,pathname){// 返回标志与错误码在R31H寄存器。
// pathname的实际内存地址送PITR、并R1 = PITR; 长度R2= LENG; 5W、5ns。
R28 = getpidvnode(,B1L);// 获取当前进程v节点指针方法。
R31H = 0; // 初始化
checkpath(); // 检查路径权限。
read_vnode();// 以R0读入i节点及相应目录项到临时temp_v节点区域(5E)
BT1 (R0).v_dirnum.31,acs1; // 文件是存在的、跳。
acs0:
R31H.15 = 0; RET // 文件不存在、置错误标志返回
acs1:
checkugid(); // 检查是否拥有者、和所属组用户,还是其它用户。
// 并置相应的权限到R31H.2-0;入口:R28、R0、R31H。
RET
}
进程对另一个进程的权限判断方法:R31H= accesspid(,pid); 系统API方法。
入口:pid进程号送R1L寄存器,当前进程号是在B1L寄存器。
出口:标志与错误码在R31H 寄存器。
占用:R0、R28、9W
耗时:15ns +
accesspath(,pid){// 返回标志与错误码在R31H寄存器。
R31H = 0; // 初始化标志、错误号。
R28 = getpidvnode();// 获取另一进程v节点指针方法。
R0 = R28;
if (R0).inode == 0 goto acs0; // 另一进程是不存在、跳。
R28 = getpidvnode(,B1L);// 获取当前进程v节点指针方法。
JMP acs1;
检查是否拥有者、和所属组用户,还是其它用户及权限的方法checkugid();
入口:R0指向临时文件v节点、或另一进程的v节点,R28 = 当前进程v节点指针。
出口:标志、错误号在R31H。
占用:26W
耗时:48ns
checkugid(){//
R1 = (R28).v_uid; // R1为当前进程的用户号。
R2L= (R0).v_mode; // 读取文件、或另一进程的权限。
R4L = 1;
if R1 != 0 goto che1; // 非根用户跳。
R31H.14 = 1; // 置根用户标志。
R31H.10-8 = R2L.8-6;// 提取根用户权限,位段赋值指令1W、1ns,
RET
che1:
R3 = (R28).p_uid.E; // R3指向当前进程的用户号数组行。
B2 = 10.CMP.0.1;// 设置多功能模块为字比较相等指令
B3 = (R0).v_uid; // B3为文件、或另一进程的用户号。
ugcmp();// 比较,16ns
BT0 PSR.YJ, che2; // 失败、为非拥有者、跳。
R31H.13 = 1; // 置进程是拥有者标志。
R31H.10-8 = R2L.11-9;// 提取拥有者权限,位段赋值指令1W、1ns,
RET
che2:
R3 = (R28).p_gid.E; // R3指向当前进程的用户组号数组行。
B2 = 2.CMP.0.1; // 设置多功能模块为字符比较相等指令
B3 = (R0).v_gid; // B3为文件、或另一进程的组号。
ugcmp(); // 比较,16ns
BT0 PSR.YJ, che3; // 失败、为其它用户、跳。
R31H.12 = 1; // 置进程是所属组成员标志。
R31H.10-8 = R2L.5-3;// 提取组成员权限,位段赋值指令1W、1ns,
RET
che3:
R31H.10-8 = R2L.5-3;// 提取其它用户权限,位段赋值指令1W、1ns,
RET
}
多功能硬件模块CMP(无符号比较指令):最多只是比较256行中的值;位图内容不变。
B2H: 高8位的低4位CMP属性: B2H.3 字比较1/字符比较0,其它3位:
000:最小值、 001:最大值
010:等于 011:不等于
100:小于、 101:大于
110:小于等于、 111:大于等于
如、比较B3的字与1-256行中字第一个相等的位置:低4位是、1010。
如、比较B3H的字符与1-256行中字符第一个相等的位置:低4位是、0010。
如、比较B3H的字符小于1-256行中字符第一个的位置:低4位是、0100。
如果要求出所有的位置、那只能是比较128行,另128E放位置结果。
如、比较B3H的字符与1-127行中字符相等的位置:低4位是、0010;高4位是0001。结果都在128E-255E里面,R4L为符合条件的位置序号数。
B3: 32位是你需要与n行中的32位值比较的数值。n <= 256
B3H: 16位是你需要与n行中的16位值比较的数值。
B4L: 返回结果:是第一个符合条件的字或字符开始地址;B4H不变,可作记录号高半字。如果已经比较完、并失败; PSR.YJ = 0;B2H.15 = 0。
比较API方法ugcmp();我们要使用多功能硬件模块来比较进程是否拥有者、和是否所属组;因为每个用户可以有最多8个用户号、和属于16个组。每次只需比较1行。
入口: R3 = 需要比较的行指针、R4L为须比较的行数。
出口:成功PSR.YJ = 1。
占用:6W
耗时:15ns
ugcmp(){
COPY.E( YJMK,R3, R4L );// 编译后4条指令,耗时:4 ns
SS1; // 比较R4L行,找到相等序号。
RET
}
。。。待续
第十五章 文件属性类的实现
原文:http://blog.csdn.net/hhhewl/article/details/42222795