现在的位置: 首页 > 综合 > 正文

Unix文件系统研究: 4. 文件类型 用户权限

2018年05月27日 ⁄ 综合 ⁄ 共 3798字 ⁄ 字号 评论关闭
导读:ScoUnix 文件系统 文件类型 用户权限

在《文件系统研究、一 i节点》中提到了i节点的结构,如下

struct dinode
{
 ushort di_mode;  /*文件类型+用户权限*/
 ……
 time_t di_ctime; /*创建时间*/
};

 

ushort di_mode是16位2进制数,保存的就是文件类型及用户权限信息,具体结构如下:

            4             8             12            16

        u g s r w x r w x r w x

 

第1-4 位 -- 文件类型位

第5位 -- suid位

第6位 -- sgid位

第7位 -- sticky位

第8-10位 -- 文件属主权限位

第11-13 -- 文件属组权限位

第14-16 -- 其他用户权限位

 

1、文件类型分类

d -- 目录文件 f -- 普通文件  b -- 块设备文件  c -- 字符设备文件 l -- 链接文件

 

用l -l命令可以看到,红色字符部分就是文件类型:

例如:

576# l -lWv /tmp
total 22
-rw-r--r--   1 root     sys            6 Jul  5 05:39 abcnew
drwxr-xr-x   2 root     sys          512 Jul  5 07:38 test

2、文件类型位算法

从系统头文件/usr/include/sys/stat.h,可以获取如下宏定义:

/*
 * st_mode flags
 */

#define         S_IFMT  0170000 /* type of file ,文件类型掩码*/
#define         S_IFREG 0100000 /* regular 普通文件*/
#define         S_IFBLK 0060000 /* block special 块设备文件*/
#define         S_IFDIR 0040000 /* directory 目录文件*/
#define         S_IFCHR 0020000 /* character special 字符设备文件*/
#define         S_IFIFO 0010000 /* fifo */
#define         S_IFNAM 0050000 /* special named file */

#if !defined(_M_XOUT)
#define         S_IFLNK 0120000 /* symbolic link 链接文件*/
#endif /* !defined(_M_XOUT) */

#define         S_ISREG(m)      (((m) & S_IFMT) == S_IFREG)
#define         S_ISBLK(m)      (((m) & S_IFMT) == S_IFBLK)
#define         S_ISDIR(m)      (((m) & S_IFMT) == S_IFDIR)
#define         S_ISCHR(m)      (((m) & S_IFMT) == S_IFCHR)
#define         S_ISFIFO(m)     (((m) & S_IFMT) == S_IFIFO)

#define         S_ISNAM(m)      (((m) & S_IFMT) == S_IFNAM)
#if !defined(_M_XOUT)
#define         S_ISLNK(m)      (((m) & S_IFMT) == S_IFLNK)
#endif /* !defined(_M_XOUT) */

下面予以解释:

文件类型占4位

       

a、#define  S_IFMT  0170000 -- 文件类型掩码宏,0170000以0开头,表示这是一个8进制数,转换成2进制,正好是 1 111 000 000 000 000 ,高4位全置1;

b、#define  S_IFREG 0100000 -- 普通文件类型掩码,0100000,转换成2进制,1 000 000 000 000 000,最高位置1;

c、#define   S_ISREG(m)  (((m) & S_IFMT) == S_IFREG) --  判断文件是否普通文件的宏函数

举例说明:m值即为我们取到ushort di_mode,假设其2进制值为 0 011 000 000 000 000,对应的8进制为 060000  。

S_ISREG(0060000) 即 (((0060000) & 0170000 ) == 0100000) ,该值返回False,则代表该文件不是普通文件。

 

注意:这里用到的就是掩码算法,这种算法在C、C++里比比皆是,下次具文讨论其优劣。

 

3、文件权限:

文件权限分 属主权限、属主组权限、其他用户权限三种;

修改权限使用chmod命令,例如chmod 666 * ,或者chmod 777 * ;

问题:大家都知道666代表给所有用户赋予读写权限,777给所有用户赋予读写执行权限,但是知道为什么是666 ,而不是555呢?

 

举例说明:

584# chmod 666 abcnew
585# l abcnew
-rw-rw-rw-   1 root     sys            6 Jul  5 05:39 abcnew
586# chmod 222 abcnew
587# l abcnew
--w--w--w-   1 root     sys            6 Jul  5 05:39 abcnew
588# chmod 444 abcnew
589# l abcnew
-r--r--r--   1 root     sys            6 Jul  5 05:39 abcnew

590# chmod 777 abcnew
591# l abcnew
-rwxrwxrwx   1 root     sys            6 Jul  5 05:39 abcnew
注意红色字体部分权限变化。

 

4、权限位组合算法

前面提到,属主权限位占3位,如下图。

r w x

又有 2^0 = 1,执行权限 x ;

2^1 = 2 ,写权限 w;

2^2 = 4 ,读权限 r。

2^1 + 2^2 = 6 ,读写权限 rw;

2^0 + 2^1 + 2^2 = 7 ,执行 写 读权限 rwx ;

 

属主用户组权限,其他用户权限采用的是同样的算法,所以就有666,777之类;

 

到此,有关文件类型及权限的讨论结束,贴上一个小程序,检验下:

 

#include
#include
#include
#include
main()
{
 DIR * dir;
 struct dirent * ptr;
 int i;
 char type,sFileName[50];
 struct stat stbuf;

 dir =opendir("/tmp");
 while((ptr = readdir(dir))!=NULL)
 {
  snprintf(sFileName,sizeof(sFileName), "/%s/%s", "tmp", ptr->d_name);
  lstat(sFileName, &stbuf);
  /*
  d -- 目录文件   f -- 普通文件
  b -- 块设备文件   c -- 字符设备文件
  l -- 链接文件
  #define         S_ISREG(m)      (((m) & S_IFMT) == S_IFREG)
  #define         S_ISBLK(m)      (((m) & S_IFMT) == S_IFBLK)
  #define         S_ISDIR(m)      (((m) & S_IFMT) == S_IFDIR)
  #define         S_ISCHR(m)      (((m) & S_IFMT) == S_IFCHR)
  #define         S_ISFIFO(m)     (((m) & S_IFMT) == S_IFIFO)
  #define         S_ISNAM(m)      (((m) & S_IFMT) == S_IFNAM)
  #if !defined(_M_XOUT)
  #define         S_ISLNK(m)      (((m) & S_IFMT) == S_IFLNK)

  */
  if ( S_ISREG(stbuf.st_mode) )
   type = '-';
  else if (S_ISBLK(stbuf.st_mode))
   type = 'b' ;
  else if (S_ISDIR(stbuf.st_mode))
   type = 'd' ;
  else if (S_ISCHR(stbuf.st_mode))
   type = 'c' ;
  else if (S_ISFIFO(stbuf.st_mode))
   type = 'f' ;
  else if (S_ISNAM(stbuf.st_mode))
   type = 'n';
  else if (S_ISLNK(stbuf.st_mode))
   type = 'n';

  printf("[type:%c][d_name:%12s] [d_ino:%8ld] [off_t:%4ld]
[d_reclen:%4ld]/n",type,ptr->d_name,ptr->d_ino,ptr->d_off,ptr->d_reclen);
 }
}

 

-----------End------------------------

本文转自

unix - 朝花夕拾
http://blog.chinaunix.net/u/13969/showart_380265.html

抱歉!评论已关闭.