• 十一、文件和目录——文件操作函数


    11.1 access 函数

    11.1.1 函数介绍

      access(判断是否具有存取文件的权限)
      相关函数 stat,open,chmod,chown,setuid,setgid

    1 #include<unistd.h>
    2 int access(const char * pathname,int mode);
    • 函数说明
      • access()会检查是否可以读/写某一已存在的文件。
    • 参数说明
      • @pathname:文件路径
      • @mode:       文件访问的权限
        • 有几种情况组合,R_OK,W_OK,X_OK 和F_OK。
        • R_OK,W_OK与X_OK用来检查文件是否具有读取、写入和执行的权限。
        • F_OK    则是用来判断该文件是否存在。
        • 由于access()只作权限的核查,并不理会文件形态或文件内容,因此,如果一目录表示为“可写入”,表示可以在该目录中建立新文件等操作,而非意味此目录可以被当做文件处理。
        • 例如,你会发现DOS的文件都具有“可执行”权限,但用execve()执行时则会失败。
    • 返回值
        • 若所有欲查核的权限都通过了检查则返回0值,表示成功,只要有一权限被禁止则返回-1。
    • 错误代码
        • EACCESS 参数pathname 所指定的文件不符合所要求测试的权限。
        • EROFS 欲测试写入权限的文件存在于只读文件系统内。
        • EFAULT 参数pathname指针超出可存取内存空间。
        • EINVAL 参数mode 不正确。
        • ENAMETOOLONG 参数pathname太长。
        • ENOTDIR 参数pathname为一目录。
        • ENOMEM 核心内存不足
        • ELOOP 参数pathname有过多符号连接问题。
        • EIO I/O 存取错误。
    • 附加说明
      • 使用access()作用户认证方面的判断要特别小心,例如在access()后再做open()的空文件可能会造成系统安全上的问题。

    11.1.2 例子

      file_access.c

     1 #include <sys/types.h>
     2 #include <sys/stat.h>
     3 #include <fcntl.h>
     4 #include <unistd.h>
     5 #include <string.h>
     6 #include <errno.h>
     7 #include <stdlib.h>
     8 #include <stdio.h>
     9 
    10 int main(int argc, const char *argv[])
    11 {
    12     if(argc < 2) {
    13         fprintf(stderr, "usage: %s files
    ", argv[0]);
    14         exit(1);
    15     }
    16 
    17     int i;
    18     for(i = 1; i < argc; i++) {
    19         if(access(argv[i], R_OK)) {
    20             printf("%d can not read %s
    ", getpid(), argv[i]);
    21         } else {
    22             printf("%d can read %s
    ", getpid(), argv[i]);
    23         }
    24         
    25         if(access(argv[i], W_OK)) {
    26             printf("%d can not write %s
    ", getpid(), argv[i]);
    27         } else {
    28             printf("%d can write %s
    ", getpid(), argv[i]);
    29         }
    30 
    31         if(access(argv[i], X_OK)) {
    32             printf("%d can not excu %s
    ", getpid(), argv[i]);
    33         } else {
    34             printf("%d can excu %s
    ", getpid(), argv[i]);
    35         }
    36 
    37         if(access(argv[i], F_OK)) {
    38             printf("%d not exist %s
    ", getpid(), argv[i]);
    39         } else {
    40             printf("%d exist %s
    ", getpid(), argv[i]);
    41         }
    42     }
    43     return 0;
    44 }

      编译执行:

      

    11.2 设置文件访问权限函数

    11.2.1 umask 函数 

      umask(设置建立新文件时的权限遮罩)
      相关函数 creat,open

    1 #include<sys/types.h>
    2 #include<sys/stat.h>
    3 mode_t umask(mode_t mask);
    • 函数说明
      • umask() 会将系统 umask 值设成参数 mask&0777 后的值,然后将先前的 umask 值返回。
      • 在使用 open() 建立新文件时,该参数 mode 并非真正建立文件的权限,而是 (mode&~umask) 的权限值。
      • 例如,在建立文件时指定文件权限为 0666,通常 umask 值默认为 022 ,则该文件的真正权限则为 0666&~022=0644,也就是rw-r--r--,通俗说就是原有的权限 - 掩码设置的权限,最后就是文件的当前的真实权限
      • 掩码设置的权限仅仅影响当前的进程,不会影响外面的 shell 。
    • 函数功能:
      • 位当前进程设置文件方式创建屏蔽字,并返回以前的值
    • 其他说明:
      • 被 umask 设置过的权限不能再使用在创建文件的权限上  
    • 返回值
      • 此调用不会有错误值返回。
      • 返回值为原先系统的umask值。

    11.2.2 chmod 和  fchmod 函数 

      chmod fchmod(改变文件的权限)
      相关函数 stat,open,chown

    1 #include<sys/types.h>
    2 #include<sys/stat.h>
    3 int chmod(const char * path,mode_t mode);
    4 int fchmod(int fd,mode_t mode);
    • 函数说明
      • 更改现存文件的权限。chmod 函数在指定的文件上进行操作,而 fchmod 函数则对已打开的文件进行操作
      • chmod() 或 fchmod() 会依参数 mode 权限来更改参数 path 指定文件 或 fd 的权限。
    • 参数
      • @mode 有下列数种组合,这些权限是用在 open 函数中的mode 和 umask 的 mode 中
        • S_ISUID 04000 文件的(set user-id on execution)位
        • S_ISGID 02000 文件的(set group-id on execution)位
        • S_ISVTX 01000 文件的sticky位,保存正文信息
        • S_IRWXU     文件所有者读写执行权限
        • S_IRUSR(S_IREAD) 00400 文件所有者具可读取权限
        • S_IWUSR(S_IWRITE)00200 文件所有者具可写入权限
        • S_IXUSR(S_IEXEC) 00100 文件所有者具可执行权限
        • S_IRWXG    用户组 读写执行权限
        • S_IRGRP 00040 用户组具可读取权限
        • S_IWGRP 00020 用户组具可写入权限
        • S_IXGRP 00010 用户组具可执行权限
        • S_IRWXO   其他用户读写执行权限
        • S_IROTH 00004 其他用户具可读取权限
        • S_IWOTH 00002 其他用户具可写入权限
        • S_IXOTH 00001 其他用户具可执行权限
        • 只有该文件的所有者或有效用户识别码为0,才可以修改该文件权限。
        • 基于系统安全,如果欲将数据写入一执行文件,而该执行文件具有S_ISUID 或S_ISGID 权限,则这两个位会被清除。
        • 如果一目录具有S_ISUID 位权限,表示在此目录下只有该文件的所有者或 root 可以删除该文件。
    • 返回值
      • 权限改变成功返回0,失败返回-1,错误原因存于errno。
    • 错误代码
      • EBADF 参数fildes为无效的文件描述词。
      • EPERM 进程的有效用户识别码与欲修改权限的文件拥有者不同,而且也不具root权限。
      • EACCESS 参数path所指定的文件无法存取。
      • EROFS 欲写入权限的文件存在于只读文件系统内。
      • EFAULT 参数path指针超出可存取内存空间。
      • EINVAL 参数mode不正确
      • ENAMETOOLONG 参数path太长
      • ENOENT 指定的文件不存在
      • ENOTDIR 参数path路径并非一目录
      • ENOMEM 核心内存不足
      • ELOOP 参数path有过多符号连接问题。
      • EIO I/O 存取错误
    •  想要改变一个文件的权限位,需满足以下条件:
      • 进程的有效用户 ID 必须等于文件的所有者ID
      • 或者进程具有超级用户权限 

      文件的所有者ID:

      

      第一个 rk3399 就是文件的所有者,第二个 rk3399  为文件所有者所在的组

      

      有效用户,就是当前程序的运行(进程),即启动程序的用户。

      一般有效用户和文件所有者是一样的

    11.2.3 例子

    (1) umask 应用

      file_chmod.c

     1 #include <unistd.h>
     2 #include <string.h>
     3 #include <fcntl.h>
     4 #include <stdio.h>
     5 #include <stdlib.h>
     6 #include <errno.h>
     7 #include <sys/types.h>
     8 #include <sys/stat.h>
     9 #include <sys/types.h>
    10 
    11 /* 用户可读写执行权限,组可读写执行权限,其他可读写执行权限 */
    12 #define MODE S_IRWXU | S_IRWXG | S_IRWXO
    13 /* 掩码权限宏,用户可执行权限,组可写可执行权限,其他可读权限 */
    14 #define UMASK S_IXUSR | S_IWGRP | S_IXGRP | S_IRWXO
    15 
    16 int main(int argc, char *argv[])
    17 {
    18     if(argc < 2) {
    19         fprintf(stderr, "usage: %s file
    ", argv[0]);
    20         exit(1);
    21     }
    22 
    23     //设置掩码
    24     umask(UMASK);
    25     // O_EXCL 和 O_CREAT 同时设置,此指令会去检查文件是否存在。
    26     // 文件若不存在则建立该文件,否则将导致打开文件错误。
    27     int fd = open(argv[1], O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, MODE);
    28     if(fd < 0) {
    29         perror("open error");
    30         exit(1);
    31     }
    32 
    33     close(fd);
    34 
    35     return 0;
    36 }

      当前的 umask  值:

      

      当前的 test.txt  的权限

      

       运行程序后:

      

      可以看见,当前shell 的  umask 是不受我们运行的 bin/file_chmod 进程的影响的,且文件创建之后的权限已经做了修改:

      组用户去掉了写权限,其他用户去掉了读执行权限,

    (2) chmod 应用

      针对上面的 test.txt  文件做修改权限操作

      file_chmod.c

     1 #include <unistd.h>
     2 #include <string.h>
     3 #include <fcntl.h>
     4 #include <stdio.h>
     5 #include <stdlib.h>
     6 #include <errno.h>
     7 #include <sys/types.h>
     8 #include <sys/stat.h>
     9 #include <sys/types.h>
    10 
    11 /* 用户可读写执行权限,组可读写执行权限,其他可读写执行权限 */
    12 #define MODE S_IRWXU | S_IRWXG | S_IRWXO
    13 /* 掩码权限宏,用户可执行权限,组可写可执行权限,其他可读权限 */
    14 #define UMASK S_IXUSR | S_IWGRP | S_IXGRP | S_IRWXO
    15 
    16 int main(int argc, char *argv[])
    17 {
    18     if(argc < 2) {
    19         fprintf(stderr, "usage: %s file
    ", argv[0]);
    20         exit(1);
    21     }
    22 
    23     //更改以读写方式打开的文件的权限
    24     int fd = open(argv[1], O_RDWR);
    25     if(fd < 0) {
    26         perror("open error");
    27         exit(1);
    28     }
    29 
    30     fchmod(fd, MODE);
    31     close(fd);
    32 
    33         return 0;
    34 }  

      编译运行结果:

      

      可以看到文件权限已经修改

  • 相关阅读:
    yellow joke 3
    JavaScript下拉菜单(1)
    Java程序员面试三十二问
    Oracle里时间的应用
    ·Java读取properties文件
    Web 窗体用户控件
    怎么解决层被flash挡住的问题?
    自定义控件
    关于mysql中的DDL,DML,DQL和DCL
    自定义一个简单连接池以及常见连接池的使用
  • 原文地址:https://www.cnblogs.com/kele-dad/p/9061989.html
Copyright © 2020-2023  润新知