Chinaunix首页 | 论坛 | 博客
  • 博客访问: 204923
  • 博文数量: 70
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 412
  • 用 户 组: 普通用户
  • 注册时间: 2013-08-30 11:07
文章分类

全部博文(70)

文章存档

2014年(68)

2013年(2)

我的朋友

分类: C/C++

2014-01-07 09:58:08

在《文件系统研究、一 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------------------------
阅读(8808) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~