Linux之文件类型和权限的获取与操作

最近两天学习了有关文件属性的获取和操作,下面是在学习过程中的一个例程。

Linux中有关文件属性的信息存储在struct stat这个结构体中:

 struct stat {
               dev_t     st_dev;     /* ID of device containing file */
               ino_t     st_ino;     /* inode number */
               mode_t    st_mode;    /* protection */
               nlink_t   st_nlink;   /* number of hard links */
               uid_t     st_uid;     /* user ID of owner */
               gid_t     st_gid;     /* group ID of owner */
               dev_t     st_rdev;    /* device ID (if special file) */
               off_t     st_size;    /* total size, in bytes */
               blksize_t st_blksize; /* blocksize for file system I/O */
               blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
               time_t    st_atime;   /* time of last access */
               time_t    st_mtime;   /* time of last modification */
               time_t    st_ctime;   /* time of last status change */
           };
我们可以通过系统API stat()获取文件的该结构体。例程中,我主要解析了st_mode这一结构体元素,该元素存储了有关文件类型和权限的信息。

类型和权限都是通过位标志进行存储和识别的:

         S_IFMT     0170000   bit mask for the file type bit fields
           S_IFSOCK   0140000   socket
           S_IFLNK    0120000   symbolic link
           S_IFREG    0100000   regular file
           S_IFBLK    0060000   block device
           S_IFDIR    0040000   directory
           S_IFCHR    0020000   character device
           S_IFIFO    0010000   FIFO
           S_ISUID    0004000   set UID bit
           S_ISGID    0002000   set-group-ID bit (see below)
           S_ISVTX    0001000   sticky bit (see below)
           S_IRWXU    00700     mask for file owner permissions
           S_IRUSR    00400     owner has read permission
           S_IWUSR    00200     owner has write permission
           S_IXUSR    00100     owner has execute permission
           S_IRWXG    00070     mask for group permissions
           S_IRGRP    00040     group has read permission

           S_IWGRP    00020     group has write permission
           S_IXGRP    00010     group has execute permission
           S_IRWXO    00007     mask for permissions for others (not in group)
           S_IROTH    00004     others have read permission
           S_IWOTH    00002     others have write permission
           S_IXOTH    00001     others have execute permission
可以看到,文件类型和权限由不同的掩码进行控制,特定的类型和权限都对应不同的位,可以通过比对位标识识别某一文件的类型或是权限。


另外,文件类型除了用上述的方法进行识别外,linux中还提供了专门的带参宏定义,通过这些宏定义可以更加方便的识别文件类型:

       S_ISREG(m)  is it a regular file?

           S_ISDIR(m)  directory?

           S_ISCHR(m)  character device?

           S_ISBLK(m)  block device?

           S_ISFIFO(m) FIFO (named pipe)?

           S_ISLNK(m)  symbolic link? (Not in POSIX.1-1996.)

           S_ISSOCK(m) socket? (Not in POSIX.1-1996.)
m就是st_mode元素。这种方法在例程中也有使用。


例程如下:

#include
#include
#include 
#include 
#include 
#include 

int main(int argc,char *argv[])
{
        int ret = -1;
        struct stat buf;
        memset(&buf,0,sizeof(struct stat));

        ret = stat(argv[1],&buf);//获取结构体struct stat的信息
        if(ret < 0)
        {
                perror("open");
                exit(-1);
        }
        printf("ino_t:%d\n",buf.st_ino);//打印inode
        
        if(1 == S_ISREG(buf.st_mode))//identify file types using macros,用带参宏定义判断文件类型
        {
                printf("%s is a regular file\n",argv[1]);
        }
        printf("S_ISLNK(buf.st_mode) is:%d\n",S_ISLNK(buf.st_mode));
        if(1 == S_ISLNK(buf.st_mode))//can't pass the test,判断符号链接文件,但在测试的时候没有判断出来
        {
                printf("%s is a symbolic link\n",argv[1]);
        }

        printf("S_IFREG:%d,buf.st_mode:%d\n",S_IFREG,buf.st_mode);//打印st_mode信息
        switch(S_IFMT & buf.st_mode)//用掩码和位标志判断文件类型
        {
                case S_IFREG:printf("%s is a regular file\n",argv[1]);break;
                case S_IFDIR:printf("%s is a directory\n",argv[1]);break;
                case S_IFSOCK:printf("%s is a socket file\n",argv[1]);break;
                case S_IFLNK:printf("%s is a link file\n",argv[1]);break;
                case S_IFBLK:printf("%s is a block device file\n",argv[1]);break;
                case S_IFCHR:printf("%s is a character device file\n",argv[1]);break;
                case S_IFIFO:printf("%s is a FIFO/pipe file\n",argv[1]);break;
                default:printf("can't identify\n");
        }

         switch(S_IRWXU & buf.st_mode)//用位标志判断文件权限
        {
                case S_IRUSR|S_IWUSR|S_IXUSR:printf("owner of %s has rwx permission \n",argv[1]);break;
                case S_IWUSR:printf("owner of %s has w permission\n",argv[1]);break;
                case S_IXUSR:printf("owner of %s has x permission\n",argv[1]);break;
                case S_IRUSR:printf("owner of %s has r permission \n",argv[1]);break;
                case S_IWUSR|S_IXUSR:printf("owner of %s has wx permission \n",argv[1]);break;
                case S_IRUSR|S_IXUSR:printf("owner of %s has rx permission \n",argv[1]);break;
                case S_IRUSR|S_IWUSR:printf("owner of %s has rw permission \n",argv[1]);break;
                default:printf("owner of %s has no permission\n");
        }
        return 0;
}

权限识别只是识别了文件属主对文件的操作权限,其它的组权限和其他权限如法炮制。由于权限是w r x的组合,而文件类型的位标识是单独的,所以两者在判断的时候略有不同。

测试时候的一个发现:有关符号链接文件(软连接文件)本身都是rwx属性,而且用chmod命令修改权限也是无效的。但其st_mode代表的则是所链接的文件的权限。换句话说符号连接文件本身都是可读可写可执行的,但其st_mode则和源文件保持一致。

测试发现的一个问题:符号链接文件被当作了普通文件,带参宏定义和位标志都无法正确识别符号连接文件。

你可能感兴趣的:(Linux应用编程/网络编程)