博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【读书笔记--Linux】Linux文件管理
阅读量:4920 次
发布时间:2019-06-11

本文共 8976 字,大约阅读时间需要 29 分钟。

一  文件的状态信息

    每个文件都有自己的状态信息,如文件的大小、文件的所有者以及修改日期等,这些是与文件的内容分开存储的。

    Linux下使用stat函数获得一个文件的状态

int stat(const char*  file_name, struct stat*  buf)int fstat(int fd, struct stat * buf) int  lstat (const char * file_name, struct stat * buf);

函数说明:

 stat函数的pathname指定文件的路径,该函数从内核中取得文件的状态并将其存储在stat结构中返回给用户,成功返回0,失败返回-1。fstat函数和stat函数类似,只是fstat函数使用文件描述符作为函数参数。lstat函数与stat函数作用一样,其差别在于,当文件本身为链接文件时,lstat会返回链接文件本身的状态信息。

stat的结构及说明

struct stat

{
dev_t st_dev; /*文件的设备编号*/
ino_t st_ino; /*文件的i-node*/
mode_t st_mode; /*文件的类型和存取的权限*/
nlink_t st_nlink; /*n 连到该文件的硬连接数目,刚建立的文件值为1 */
uid_t st_uid; /*文件所有者的用户识别码*/
gid_t st_gid; /*文件所有者的组识别码*/
dev_t st_rdev; /*若此文件为装置设备文件,则为其设备编号 */
off_t st_size; /*文件大小,以字节计算*/
unsigned long st_blksize; /*文件系统的I/O 缓冲区大小 */
unsigned long st_blocks; /*占用文件区块的个数,每一区块大小为512 个字节*/
time_t st_atime; /* 文件最近一次被存取或被执行的时间,一般只有在用mknod、utime、read、write与tructate时改变*/
time_t st_mtime; /*  文件最后一次被修改的时间,一般只有在用mknod、utime和write时才会改变 */
time_t st_ctime; /* 最近一次被更改的时间,此参数会在文件所有者、组、权限被更改时更新先前所描述的st_mode*/
};

 

二 文件的类型

      Linux环境下的文件共有以下七种:

  • 普通文件(regular file):常见的二进制可执行文件和文本文件都是普通文件。
  • 目录文件(directory file):目录文件中存放目录下文件的名字和指向它们信息的指针。目录虽然也是一种文件,但是必须使用特殊的目录系统调用去操作。
  • 块特殊文件(block  special file):Linux将硬件设备也抽象为文件,块特殊文件就是对带缓冲的设备的抽象。
  • 字符特殊文件(character special file):与块设备对应的是字符设备,字符设备是不带缓冲的设备的抽象。Linux中的设备不是块设备就是字符设备。
  • 命名管道(named pipe, FIFO):用于进程间通信的特殊文件,只存在与内核中。
  • 符号链接(symbolic link):指向另外一个文件的文件,分为符号链接和硬链接
  • 套接字(socket):用于网络进程之间通信的文件,也可用于同一主机内进程的通信。

     在stat结构文件类型存储在st_mode中,它是一个位向量。由于Linux中一共有七种文件,所以只要用3位二进制就可以表示所有的文件类型了。Linux用宏来去的相应的二进制位,从而判断文件的类型。如下是定义在sys/stat.h中的宏定义。

S_ISREG() 普通文件
S_ISDIR() 目录文件
S_ISCHR() 字符特殊发文件
S_ISBLK() 块特殊文件
S_ISFIFO() 命名管道
S_ISLNK() 符号链接
S_ISSOCK() 套接字

 三 文件权限

       Linux环境下所有的文件都有访问限制,成为文件的访问权限。每个文件的访问权限分为三类:

  • 文件所有者(u)
  • 文件所有者所在的组(g)
  • 其他的所有用户(o)

每类访问权限又分为三个权限标志位:

  • 可读(r)
  • 可写(w)
  • 可执行(x)

      三三得九,所以Linux下文件共有9个权限标志位。Linux提供了测试宏来判断指定的权限标志位是否有权限,方法是使用stat中st_mode域与相应的宏进行与操作,进而判断该位是否有相应的权限。如果有则宏返回true,否则返回false。

文件权限位测试宏
S_IRUSR 0400 用户-读
S_IWUSR 0200 用户-写
S_IXUSR 0100 用户-执行
S_IRGRP 0040 组-读
S_IWGRP 0020 组-写
S_IXGRP 0010 组-执行
S_IROTH 0004 其他用户-读
S_IWOTH 0002 其他用户-写
S_IXOTH 0001 其他用户-执行

 

四   设置用户ID和组ID 位

      一个进程通常属于某个用户,一个文件也是如此,与文件权限相关的进程ID分为4中情况,如下所示:

与进程有关的用户ID和组ID
进程用户ID和组ID 表示的意义
ruid 实际用户ID
euid 有效用户ID
rgid 实际组ID
egid 有效组ID
  • 实际用户ID:表示进程实际属于哪个用户,通常进程由哪个用户创建,则进程的实际用户ID就是哪个用户。该值一般不会改变,除非调用setuid()函数。
  • 有效用户ID:表示进程目前实际具有的用户权限。即该进程得到了某个用户的授权,暂时成为该用户的进程,从而具有与该用户其他进程同样的权限。
  • 实际组ID:类似与实际用户ID,应用与用户组方面。
  • 有效组ID:类似与有效用户ID,应用与用户组方面。

      文件的设置用户ID位和设置组ID位,可以使进程的有效用户ID和有效组ID等同与文件所有者的用户ID和组ID,使进程获得等同于文件所有者的权限。进程的用户ID和组ID是在调用exec函数时改变的,因此设置用户ID位和设置组ID位只对可执行文件起作用。Linux提供了宏测试来判断设置用户ID位和设置组ID位是否被设置。如下

设置用户ID和设置组ID的位测试宏
st_mode测试宏 宏的值(八进制) 意义
S_ISUID 042000 设置用户ID
S_ISGID 02000 设置组ID

进程在打开文件时所做的测试如下:

  1. 若进程的有效用户ID是0,即,该进程属于根用户或得到了跟用户的授权,则可以访问。
  2. 若进程的有效用户ID和文件所有者的用户ID一致,并且文件所有者适当的文件权限位已被设置,则可以访问。
  3. 若进程的有效用户ID和文件的组用户ID一致,并且文件的组用户文件权限位已经设置,则可以访问。
  4. 若进程的有效用户ID不满足以上三个条件,则不能访问。

五 文件权限操作   

    1 测试文件访问权限

       Linux下使用access函数对文件的访问权限进行测试。

相关函数
stat,open,chmod,chown,setuid,setgid
表头文件
#include<unistd.h>
定义函数
int access(const char * pathname,int mode);
函数说明
access()会检查是否可以读/写某一已存在的文件。参数mode有几种情况组合,R_OK,W_OK,X_OK 和F_OK。R_OK,W_OK与X_OK用来检查文件是否具有读取、写入和执行的权限。F_OK则是用来判断该文件是否存在。由于access()只作 权限的核查,并不理会文件形态或文件内容,因此,如果一目录表示为“可写入”,表示可以在该目录中建立新文件等操作,而非意味此目录可以被当做文件处理。 例如,你会发现DOS的文件都具有“可执行”权限,但用execve()执行时则会失败。
返回值
若所有欲查核的权限都通过了检查则返回0值,表示成功,只要有一权限被禁止则返回-

        access函数使用当前进程的实际用户ID和实际组ID与文件的所有者ID和组ID进行比较。比较方法如下:

  • 如果进程的实际用户ID和文件的所有者ID相等,使用参数mode指定的权限与文件所有者的权限进行比较。
  • 如果上一条件不成立,且进程的实际组ID和文件的组ID相等,则使用参数mode指定的权限与文件所有者的权限进行比较。
  • 如果上述条件都不成立,则使用参数mode与文件的其他用户权限进行比较。

测试下

1 #include
2 #include
3 #include
4 #include
5 #include
6 7 int main(void) 8 { 9 int fd; //文件描述符10 struct stat statbuf; //存储文件状态信息11 pid_t pid; //进程ID12 uid_t ruid,euid; //进程的实际用户ID和有效用户ID 13 14 //取得文件状态15 if(stat("test.txt", &statbuf) == -1){ 16 perror("获取文件状态失败: \n");17 exit(1);18 }19 20 //得到进程的实际用户ID和有效用户ID21 if((ruid = getuid()) == -1 || (euid = geteuid()) == -1){22 perror("获得进程有效用户ID失败\n");23 exit(1);24 }25 26 //打印进程的实际用户ID和有效用户ID27 printf("当前进程的实际用户ID为:%u,有效用户ID为:%u\n", ruid, euid);28 29 //打印文件所有者的ID30 printf("文件所有者为:%u\n", statbuf.st_uid);31 32 //测试文件权限33 if(access("test.txt", R_OK) == -1){34 perror("测试失败\n");35 exit(1);36 }37 38 printf("获取 成功\n");39 40 41 return 0;42 43 }

         2 文件权限屏蔽字umask

     使用umask权限屏蔽字,可以屏蔽一些不希望用户干预设置的权限位。即使用户对这些权限位进行设置,系统在创建文件时也会忽略用户对该位指定的值,将其设置为0。

umask(设置建立新文件时的权限遮罩)
相关函数
creat,open
表头文件
#include<sys/types.h>
#include<sys/stat.h>
定义函数
mode_t umask(mode_t mask);
函数说明
umask()会将系统umask值设成参数mask&0777后的值,然后将先前的umask值返回。在使用open()建立新文件时,该参数 mode并非真正建立文件的权限,而是(mode&~umask)的权限值。例如,在建立文件时指定文件权限为0666,通常umask值默认为 022,则该文件的真正权限则为0666&~022=0644,也就是rw-r--r--返回值此调用不会有错误值返回。返回值为原先系统的 umask值。

         下面在shell中使用文件权限屏蔽字进行测试:

  1. 打开shell]终端,使用umask检查当前权限屏蔽字

            

       2. 创建一个新文件,检查其权限是否被设置

             

       3. 再次使用umask命令改变权限屏蔽字,再察看创建后的文件权限情况

          

          可以看到此时文件的其他用户权限的可读权限被屏蔽了。

           下面在程序中使用文件权限屏蔽字进行测试,程序如下:

          

1 #include
2 #include
3 #include
4 #include
5 6 /*屏蔽所有者,组用户和其他用户的可读权限*/ 7 #define MASK S_IRUSR | S_IRGRP | S_IROTH 8 9 int main()10 {11 int fd;12 mode_t mask;13 struct stat buf;14 15 //改变文件权限屏蔽字,并将原来的屏蔽字保存16 mask = umask(MASK);17 18 printf("原始权限屏蔽字为:%x\n", mask);19 20 //使用新文件的所有者,组用户和其他用户的权限全部被设置21 if( (fd = creat("tmp.txt",777)) == -1){22 perror("创建文件失败\n");23 exit(1);24 }25 26 //获取文件的状态信息27 if(stat("tmp.txt", &buf) == -1){28 perror("获取文件状态信息失败\n");29 exit(1);30 }31 32 //测试文件的读属性33 if( (buf.st_mode & S_IRUSR) != 0)34 printf("文件tmp的所有者具有读权限\n");35 else36 printf("文件tmp的所有者不具有读权限\n");37 38 if( (buf.st_mode & S_IRGRP) != 0)39 printf("文件tmp的所在组具有读权限\n");40 else41 printf("文件tmp的所在组不具有读权限\n");42 43 if( (buf.st_mode & S_IROTH) != 0)44 printf("文件tmp的其他用户具有读权限\n");45 else46 printf("文件tmp的其他用户不具有读权限\n");47 48 49 close(fd);50 }

 运行结果如下:

      

     可以看到文件的所有可都权限都被屏蔽了。

 

      3 改变文件权限

             只有文件的所有者和根用户可以改变文件的权限。

              Linux函数使用chmod和fchmod函数来改变文件的权限。

                chmod函数

相关函数
fchmod,stat,open,chown
表头文件
#include<sys/types.h>
#include<sys/stat.h>
定义函数
int chmod(const char * path,mode_t mode);
函数说明
chmod()会依参数mode 权限来更改参数path 指定文件的权限。
参数
mode 有下列数种组合
S_ISUID 04000 文件的(set user-id on execution)位
S_ISGID 02000 文件的(set group-id on execution)位
S_ISVTX 01000 文件的sticky位
S_IRUSR(S_IREAD) 00400 文件所有者具可读取权限
S_IWUSR(S_IWRITE)00200 文件所有者具可写入权限
S_IXUSR(S_IEXEC) 00100 文件所有者具可执行权限
S_IRGRP 00040 用户组具可读取权限
S_IWGRP 00020 用户组具可写入权限
S_IXGRP 00010 用户组具可执行权限
S_IROTH 00004 其他用户具可读取权限
S_IWOTH 00002 其他用户具可写入权限
S_IXOTH 00001 其他用户具可执行权限
只有该文件的所有者或有效用户识别码为0,才可以修改该文件权限。基于系统安全,如果欲将数据写入一执行文件,而该执行文件具有S_ISUID 或S_ISGID 权限,则这两个位会被清除。如果一目录具有S_ISUID 位权限,表示在此目录下只有该文件的所有者或root可以删除该文件。
返回值
权限改变成功返回0,失败返回-1,错误原因存于errno。

             

                fchmod函数

相关函数
chmod,stat,open,chown
表头文件
#include<sys/types.h>
#include<sys/stat.h>
定义函数
int fchmod(int fildes,mode_t mode);
函数说明
fchmod()会依参数mode权限来更改参数fildes所指文件的权限。参数fildes为已打开文件的文件描述词。参数mode请参考chmod()。
返回值
权限改变成功则返回0,失败返回-1,错误原因存于errno。

          3.1 在shell中改变文件权限

               改变文件权限主要有两种方法:

  •  直接使用一个确定好的权限字改变权限。如使用权限字0777添加文件所有者的用户权限。
  • 使用相对权限,就是在原有的文件权限基础上添加若干权限,如新权限字 = 旧权限字 | 0004。

       在shell中调用chmod改变文件权限,有两种使用方法:文字设定法数字设定法 

              文字设定法,如下图

           

            数字设定法,如下图

             

          3.2 在程序中改变文件权限

                代码如下:

1 #include
2 #include
3 #include
4 #include
5 #include
6 7 8 #define RD_MODE S_IRUSR | S_IRGRP | S_IROTH //读文件权限 9 #define WR_MODE S_IWUSR | S_IWGRP | S_IWOTH //写文件权限10 #define EX_MODE S_IXUSR | S_IXGRP | S_IXOTH //文件执行权限11 12 int main()13 {14 int fd;15 struct stat statbuf;16 mode_t mode;17 18 printf("程序开始\n");19 sleep(5);20 21 //使用绝对权限字改变test.txt的权限22 if(chmod("test.txt", RD_MODE) == -1){23 perror("改变文件权限失败\n");24 exit(1);25 }else26 printf("使用绝对权限字改变文件权限成功\n");27 28 //获取文件的状态信息29 if(stat("test.txt", &statbuf) == -1){30 perror("获取文件状态失败\n");31 exit(1);32 }33 34 sleep(10);35 36 //使用相对权限字改变文件权限37 mode = statbuf.st_mode; //取得文件权限字38 mode &= (~S_IRWXU & ~S_IRWXG & ~S_IRWXO); //关闭文件所有的权限39 mode |= (WR_MODE);40 41 if(chmod("test.txt", mode) == -1){42 perror("使用相对权限字改变文件权限失败\n");43 exit(1);44 }else45 printf("使用相对权限字改变文件权限成功\n");46 47 sleep(10);48 49 //使用fchmod改变文件权限50 fd = open("./test.txt", O_WRONLY);51 if(fchmod(fd, EX_MODE) == -1){52 perror("改变文件权限失败\n");53 exit(1);54 }else55 printf("使用fchmod函数改变文件权限成功\n");56 57 printf("完成\n");58 59 60 return 0;61 }

     程序在执行之前test.txt的权限如下:

        

      使用chmod改变文件权限为RD_MODE后的权限为:

               

     使用chmod改变文件权限为WR_MODE后的权限为:

        

     使用fchmod改变文件权限为EX_MODE后的权限为:

       

      

转载于:https://www.cnblogs.com/1314NNNKKK/archive/2013/05/03/3056509.html

你可能感兴趣的文章
iOS 开发常用的一些工具
查看>>
CAAnimation动画的一些知识点
查看>>
雨后图标
查看>>
php 去除二维数组中的包含某一个值的数组
查看>>
CopyOnWrite容器
查看>>
【nginx】配置详解
查看>>
Flex各个keycode值对照
查看>>
react 从0到1
查看>>
ASP.NET 用 Office COM 组件将 docx\pptx\xlsx 转换成 PDF 文件
查看>>
oracle外部表的使用
查看>>
Liptables 从入门到应用
查看>>
SQL语句优化技术分析
查看>>
怎样用好ZBrush中的PaintStop插件
查看>>
mysql触发器使用if..then sql elseif then end if; 转自 吴大哥
查看>>
OO模式-Singleton
查看>>
Java 手机短号
查看>>
Explain:H5+Webapp+MUI App 页面滑至到底部自动加载新的内容
查看>>
跨过边界的孩童( A Child Breaking Boundary)
查看>>
053第18
查看>>
Sass安装
查看>>