• [置顶] 文件和目录(一)--unix环境高级编程


         普通文件和目录linux中最多的两类文件,linux中一共有七种类型的文件,如下:

    1.普通文件
    2.目录
    3.字符特殊设备
    4.块特殊设备
    5.FIFO,又叫命名管道
    6.Socket,即套接字
    7.符号链接


    获取一个文件的详细信息可以使用stat函数组,stat函数组包括三个函数,它们的函数原型如下:

    int stat(const char* pathname,struct stat* buf);
    int fstat(int filedes,struct stat* buf);
    int lstat(const char* pathname,struct stat* buf);


    这三个函数的功能大同小异,都是将一个文件的相关信息存入到一个stat结构体变量中,也就是提供的第二个参数。stat函数的第一个参数为文件的路径名字,fstat的第一个参数为打开文件的文件描述符,lstat函数与前面的两个函数一个最大的不同是它并不跟随符号链接,即获得的不是符号链接指向的文件的信息,而是符号链接本身的信息。stat这个结构体中的成员如下:

    struct stat
    {
      mode_t st_mode; //文件的类型和权限
      ino_t st_ino; //inode的节点号
      dev_t st_dev; //设备号
      dev_t st_rdev; //特殊设备号
      nlink_t st_nlink; //连接数
      uid_t st_uid; //文件所有者
      gid_t st_gid; //文件所属组
      off_t st_st_size; //文件的字节数
      time_t st_atime; //文件的最后存取时间
      time_t mtime; //文件的最后修改时间
      time_t ctime; //文件权限的最后修改时间
      long st_blksize; //最佳的IO块长度
      long st_blocks; //512字节的块数
    };


    可以使用stat结构体中的成员的st_mode来判断文件的类型,者需要使用到<sys/stat.h>头文件中提供的一系列宏:

    S_ISREG();判断普通文件
    S_ISDIR(); 判断目录
    S_ISCHR(); 判断特殊字符设备
    S_ISBLK(); 判断块特殊设备
    S_ISFIFO(); 判断FIFO
    S_ISSOCK(); 判断是否为Socket
    S_ISLNK(); 判断是否为符号链接
    


         对每个文件都有九个基本相关的存取许可权,如下:

    S_IRUSR 用户读
    S_IWUSR 用户写
    S_IXUSR 用户执行
    
    S_IRGRP 组读
    S_IWGRP 组写
    S_IXGRP 组执行
    
    S_IROTH 其他用户读
    S_IWOTH 其他用户写
    S_IXOTH 其他用户执行
    

    在一个进程打开文件时,会按下面四步来进行:

    1.先检查改进程的有效用户ID,如果为0,说明是超级用户,则系统给改进程充分的自由去操作文件,否则进入下一步检查。
    2.检查进程的有效用户ID和文件所有者ID是否相同,如果相同则按照该文件的所有者的权限进行相关的检查,符合权限则允许操作,不符合则拒绝,直接结束。ID不同则进入下一步
    3.检查进程的有效组ID和文件所属组的ID是否相同,如果相同则按照该文件组的权限进行相关检查,符合权限则允许操作,不符合则拒绝,直接结束。ID不同则进入下一步
    4.按照该文件其他用户的权限进行相关检查,符合权限则允许操作,不符合则拒绝,直接结束。
    

    这里需要说明的是有效ID和实际ID在大多数情况下是相同的,但是当设置SUID和SGID权限时,有效ID和实际ID就不同了。另外有效ID是进程的一个性质,但是实际ID是文件的一个性质。每当新建一个文件的时候,该文件的所有者和创建文件进程的有效ID相同,该文件所属的组和该进程的有效组ID相同,也可能是该文件的组和该文件所在目录所属的组相同。

         access函数用进程的实际ID来测试进程对文件的权限,它的函数原型如下:

    int access(const char* pathname,int mode);


    如果执行成功则返回0,否则返回-1。第一个参数为所要进行测试的文件的名字,第二个参数为测试的权限,它的选择有:

    R_OK 测试读许可权
    W_OK 测试写许可权
    X_OK 测试执行许可权
    F_OK 测试文件是否存在


    mode可以是上面的几个参数按位或的结果。需要注意的是access函数只测试进程的实际ID,而不测试进程的有效ID。一定要注意这一点,否则这可能会在某些情况下给我们造成困惑。

         相信在linux下面使用过umask命令的朋友们,都对umask函数的作用一定也了解。umask函数的作用就是在进程执行时,调整umask的值,给进程创建的文件设置合适的权限,当该进程结束时,umask仍保持原来系统中的值不变。它的函数原型如下:

    mode_t umask(mode_t cmask);

    它的返回值是原来的umask的值,这也是linux系统中少数几个没有出错返回值的几个函数之一。它的作用是从创建文件时指定的权限中减掉umask中指定的权限。比如,进程创建文件时指定的用户权限是:

    rwxrwxrwx


    而且umask指定的值是022,则改进程创建的文件的权限就是755。

         chmod和fchmod函数用来改变文件的权限,它们的函数原型如下:

    int chmod(const char* pathname,mode_t mode);
    int fchmod(int filedes,mode_t mode);


    chmod在文件名上操作,而fchmod在文件描述符上进行操作。第二个参数用来指定文件要修改的权限,它是下面几个参数的按位或:

    S_ISUID 是否为SUID
    S_ISGID 是否为SGID
    S_ISVTX 是否为SBIT
    
    S_IRWXU 用户读写执行
    S_IRUSR 用户读
    S_IWUSR 用户写
    S_IXUSR 用户执行
    
    S_IRWXG 组读写执行
    S_IRGRP 组读
    S_IWGRP 组写
    S_IXGRP 组执行
    
    S_IRWXO 其他读写执行
    S_IROTH 其他读
    S_IWOTH 其他写
    S_IXOTH 其他执行

    该函数如果执行成功则返回0,若出错返回-1。关于SUID,SGID和SBIT的相关说明请参考另一篇博客:

    http://blog.csdn.net/xiaocainiaoshangxiao/article/details/17378611


    用户在使用进程修改当前文件的权限时,进程的有效用户ID必须等于文件的所有者,或者是0即超级用户。

         chown,fchown以及lchown用来改变文件的所有者和所属的组,它们的函数原型如下:

    int chown(const char* pathname, uid_t owner, gid_t group);
    int fchown(int filedes , uid_t owner, gid_t group);
    int lchown(const char* filename ,uid_t owner ,gid_t group);
    

    当该函数执行成功时,返回0,出错则返回-1。修改文件的用户ID需要据进程的有效用户ID为超级用户。当进程的有效用户ID等于文件的用户ID时,可以修改该文件组ID。

  • 相关阅读:
    OSPF 相关知识点
    基于LINUX 主机防火墙的端口转发
    WSUS服务器硬盘空间不足,如何迁移补丁文件夹
    ESXi 5.5开启并配置SNMP
    识别远程操作系统
    一个真实的社会
    "要敢杀掉旧的自己,新的自己才会诞生”读后感
    关于独立
    创业心得:从客户的抱怨中发现市场机会
    学习和思考的要点
  • 原文地址:https://www.cnblogs.com/fuhaots2009/p/3481887.html
Copyright © 2020-2023  润新知