用户权限
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 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,可以获取如下宏定义:
#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) */
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、权限位组合算法
又有 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 <sys/stat.h> #include <unistd.h>
定义函数:int stat(const char * file_name, struct stat *buf);
函数说明:stat()用来将参数file_name 所指的文件状态, 复制到参数buf 所指的结构中。
下面是struct stat 内各参数的说明:
struct stat
{
dev_t st_dev; //device 文件的设备编号
ino_t st_ino; //inode 文件的i-node
mode_t st_mode; //protection 文件的类型和存取的权限
nlink_t st_nlink; //number of hard links 连到该文件的硬连接数目, 刚建立的文件值为1.
uid_t st_uid; //user ID of owner 文件所有者的用户识别码
gid_t st_gid; //group ID of owner 文件所有者的组识别码
dev_t st_rdev; //device type 若此文件为装置设备文件, 则为其设备编号
off_t st_size; //total size, in bytes 文件大小, 以字节计算
unsigned long st_blksize; //blocksize for filesystem I/O 文件系统的I/O 缓冲区大小.
unsigned long st_blocks; //number of blocks allocated 占用文件区块的个数, 每一区块大小为512 个字节.
time_t st_atime; //time of lastaccess 文件最近一次被存取或被执行的时间, 一般只有在用mknod、utime、read、write 与tructate 时改变.
time_t st_mtime; //time of last modification 文件最后一次被修改的时间, 一般只有在用mknod、utime 和write 时才会改变
time_t st_ctime; //time of last change i-node 最近一次被更改的时间, 此参数会在文件所有者、组、权限被更改时更新
};
先前所描述的st_mode 则定义了下列数种情况:
1、S_IFMT 0170000 文件类型的位遮罩
2、S_IFSOCK 0140000 scoket
3、S_IFLNK 0120000 符号连接
4、S_IFREG 0100000 一般文件
5、S_IFBLK 0060000 区块装置
6、S_IFDIR 0040000 目录
7、S_IFCHR 0020000 字符装置
8、S_IFIFO 0010000 先进先出
9、S_ISUID 04000 文件的 (set user-id on execution)位
10、S_ISGID 02000 文件的 (set group-id on execution)位
11、S_ISVTX 01000 文件的sticky 位
12、S_IRUSR (S_IREAD) 00400 文件所有者具可读取权限
13、S_IWUSR (S_IWRITE)00200 文件所有者具可写入权限
14、S_IXUSR (S_IEXEC) 00100 文件所有者具可执行权限
15、S_IRGRP 00040 用户组具可读取权限
16、S_IWGRP 00020 用户组具可写入权限
17、S_IXGRP 00010 用户组具可执行权限
18、S_IROTH 00004 其他用户具可读取权限
19、S_IWOTH 00002 其他用户具可写入权限
20、S_IXOTH 00001 其他用户具可执行权限上述的文件类型在 POSIX 中定义了检查这些类型的宏定义
21、S_ISLNK (st_mode) 判断是否为符号连接
22、S_ISREG (st_mode) 是否为一般文件
23、S_ISDIR (st_mode) 是否为目录
24、S_ISCHR (st_mode) 是否为字符装置文件
25、S_ISBLK (s3e) 是否为先进先出
26、S_ISSOCK (st_mode) 是否为socket 若一目录具有sticky 位 (S_ISVTX), 则表示在此目录下的文件只能被该文件所有者、此目录所有者或root 来删除或改名.
返回值:执行成功则返回0,失败返回-1,错误代码存于errno。
错误代码:
1、ENOENT 参数file_name 指定的文件不存在
2、ENOTDIR 路径中的目录存在但却非真正的目录
3、ELOOP 欲打开的文件有过多符号连接问题, 上限为16 符号连接
4、EFAULT 参数buf 为无效指针, 指向无法存在的内存空间
5、EACCESS 存取文件时被拒绝
6、ENOMEM 核心内存不足
7、ENAMETOOLONG 参数file_name 的路径名称太长
stat()函数是将文件状态复制到buf中,可以利用其中的st_mode参数判断文件的状态:(举两个例子,在Tinyhttpd源码中看到的)
struct stat st;
stat(path, &st);
st.st_mode & S_IFMT == S_IFDIR; //可以判断st是否是一个目录
st.st_mode & S_IXUSR == 1; //可以判断是否可执行