美文网首页Linux/Unix知识点UNIX环境高级编程Linux学习之路
从零开始UNIX环境高级编程(4):文件和目录

从零开始UNIX环境高级编程(4):文件和目录

作者: 伤口不该结疤 | 来源:发表于2017-02-12 17:33 被阅读93次

    1. 函数stat、fstat、fstata和lstat

    1.1 函数描述

    函数原型 描述
    int stat(const char *restrict path, struct stat *restrict buf); 获得与path有关的文件信息到buf
    int fstat(int fd, struct stat *buf); 获得与文件描述符fd有关的文件信息到buf
    int fstatat(int fd, const char *path, struct stat *buf, int flag); 返回fd有关的文件信息到buf,当flag设置为AT_SYMLINK_NOFOLLOW,功能和lstat一样;当path为绝对路径时,功能和stat一样
    int lstat(const char *restrict path, struct stat *restrict buf); 和stat作用类似,只是当文件是一个符号链接时,会返回符号链接的有关信息

    1.2 stat结构体

    stat结构体在不同的版本上实现会有所不同,在Mac OSX 10.12.2上根据宏_DARWIN_FEATURE_64_BIT_INODE是否定义,stat对应有两种实现方式。

    • _DARWIN_FEATURE_64_BIT_INODE未定义
     struct stat { /* when _DARWIN_FEATURE_64_BIT_INODE is NOT defined */
         dev_t    st_dev;    /* device inode resides on */
         ino_t    st_ino;    /* inode's number */
         mode_t   st_mode;   /* inode protection mode */
         nlink_t  st_nlink;  /* number of hard links to the file */
         uid_t    st_uid;    /* user-id of owner */
         gid_t    st_gid;    /* group-id of owner */
         dev_t    st_rdev;   /* device type, for special file inode */
         struct timespec st_atimespec;  /* time of last access */
         struct timespec st_mtimespec;  /* time of last data modification */
         struct timespec st_ctimespec;  /* time of last file status change */
         off_t    st_size;   /* file size, in bytes */
         quad_t   st_blocks; /* blocks allocated for file */
         u_long   st_blksize;/* optimal file sys I/O ops blocksize */
         u_long   st_flags;  /* user defined flags for file */
         u_long   st_gen;    /* file generation number */
     };
    
    • _DARWIN_FEATURE_64_BIT_INODE已定义
     struct stat { /* when _DARWIN_FEATURE_64_BIT_INODE is defined */
         dev_t           st_dev;           /* ID of device containing file */
         mode_t          st_mode;          /* Mode of file (see below) */
         nlink_t         st_nlink;         /* Number of hard links */
         ino_t           st_ino;           /* File serial number */
         uid_t           st_uid;           /* User ID of the file */
         gid_t           st_gid;           /* Group ID of the file */
         dev_t           st_rdev;          /* Device ID */
         struct timespec st_atimespec;     /* time of last access */
         struct timespec st_mtimespec;     /* time of last data modification */
         struct timespec st_ctimespec;     /* time of last status change */
         struct timespec st_birthtimespec; /* time of file creation(birth) */
         off_t           st_size;          /* file size, in bytes */
         blkcnt_t        st_blocks;        /* blocks allocated for file */
         blksize_t       st_blksize;       /* optimal blocksize for I/O */
         uint32_t        st_flags;         /* user defined flags for file */
         uint32_t        st_gen;           /* file generation number */
         int32_t         st_lspare;        /* RESERVED: DO NOT USE! */
         int64_t         st_qspare[2];     /* RESERVED: DO NOT USE! */
     };
    
    • 通过一段代码来验证_DARWIN_FEATURE_64_BIT_INODE是否定义
    #include "../inc/apue.h"
    
    int main(int argc, char const *argv[])
    {
    #if defined(_DARWIN_FEATURE_64_BIT_INODE)
        printf("_DARWIN_FEATURE_64_BIT_INODE is defined\n");
    #else
        printf("_DARWIN_FEATURE_64_BIT_INODE is not defined \n");
    #endif
        return 0;
    }
    

    运行结果

    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ./stat_test 
    _DARWIN_FEATURE_64_BIT_INODE is defined
    

    2. 文件类型

    2.1 分类

    文件分类如下:


    文件类型

    文件类型可以通过结构体stat中的成员st_mode获取,不同类型对应的值都定义在头文件 /usr/include/sys/stat.h中:

     #define S_IFMT 0170000           /* type of file */
     #define        S_IFIFO  0010000  /* named pipe (fifo) */
     #define        S_IFCHR  0020000  /* character special */
     #define        S_IFDIR  0040000  /* directory */
     #define        S_IFBLK  0060000  /* block special */
     #define        S_IFREG  0100000  /* regular */
     #define        S_IFLNK  0120000  /* symbolic link */
     #define        S_IFSOCK 0140000  /* socket */
     #define        S_IFWHT  0160000  /* whiteout */
     #define S_ISUID 0004000  /* set user id on execution */
     #define S_ISGID 0002000  /* set group id on execution */
     #define S_ISVTX 0001000  /* save swapped text even after use */
     #define S_IRUSR 0000400  /* read permission, owner */
     #define S_IWUSR 0000200  /* write permission, owner */
     #define S_IXUSR 0000100  /* execute/search permission, owner */
    

    2.2 获取文件类型 - 示例

    • code
    #include "../inc/apue.h"
    
    int main(int argc, char const *argv[])
    {
        struct stat buf;
        char *ptr;
    
        if (argc != 2)
        {
            printf("please input a filename\n");
            return 0;
        }
    
        if (lstat(argv[1], &buf) < 0 )
            err_ret("lstat error");
    
        if (S_ISREG(buf.st_mode))
            ptr = "regular";
        else if (S_ISDIR(buf.st_mode))
            ptr = "directory";
        else if (S_ISLNK(buf.st_mode))
            ptr = "symbolic link";
        else
            ptr = "unknown mode";
    
        printf("%s\n", ptr);
    
        return 0;
    }
    

    早期的unix版本不提供S_ISxxx宏,需要先将st_mode与屏蔽字S_IFMT进行与运算,然后在和S_IFxxx常量进行比较才能得出对应的文件类型。S_ISxxx宏定义如下:

    #define S_ISBLK(m)  (((m) & S_IFMT) == S_IFBLK) /* block special */
    #define S_ISCHR(m)  (((m) & S_IFMT) == S_IFCHR) /* char special */
    #define S_ISDIR(m)  (((m) & S_IFMT) == S_IFDIR) /* directory */
    #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) /* fifo or socket */
    #define S_ISREG(m)  (((m) & S_IFMT) == S_IFREG) /* regular file */
    #define S_ISLNK(m)  (((m) & S_IFMT) == S_IFLNK) /* symbolic link */
    #define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)    /* socket */
    
    • 运行结果
    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ cc get_file_type.c -o get_file_type
    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ./get_file_type /dev/zero 
    unknown mode
    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ./get_file_type get_file_type.c 
    regular
    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ./get_file_type .
    directory
    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ./get_file_type /dev/stdin 
    symbolic link
    

    使用ls命令查看文件属性,和程序运行结果一致

    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ls -dl get_file_type.c /dev/zero . /dev/stdin 
    drwxr-xr-x  6 zhanghuamao  staff       204  2 11 09:58 .
    lr-xr-xr-x  1 root         wheel         0  2 11 09:39 /dev/stdin -> fd/0
    crw-rw-rw-  1 root         wheel    3,   3  2 11 09:39 /dev/zero
    -rw-r--r--@ 1 zhanghuamao  staff       453  2 11 10:01 get_file_type.c
    

    3. 访问权限

    3.1 文件权限

    • 可读权限

    使用chmod命令去掉文件的r权限,执行cp复制文件时,会报错"cp: file.txt: Permission denied
    "
    ,说明复制文件需要r权限

    zhanghuamaodeMacBook-Pro:test zhanghuamao$ sudo chmod a-r file.txt 
    
    zhanghuamaodeMacBook-Pro:test zhanghuamao$ cp file.txt file.txt.bk
    cp: file.txt: Permission denied
    

    给文件用户添加可读权限,复制成功

    zhanghuamaodeMacBook-Pro:test zhanghuamao$ sudo chmod u+r file.txt 
    
    zhanghuamaodeMacBook-Pro:test zhanghuamao$ ls -l file.txt
    -rw-------  1 zhanghuamao  staff  0  2 11 14:15 file.txt
    
    zhanghuamaodeMacBook-Pro:test zhanghuamao$ cp file.txt file.txt.bk
    
    zhanghuamaodeMacBook-Pro:test zhanghuamao$ ls -l
    total 0
    -rw-------  1 zhanghuamao  staff    0  2 11 14:15 file.txt
    -rw-------  1 zhanghuamao  staff    0  2 11 14:18 file.txt.bk
    

    3.2 目录权限

    • 可读权限

    目录要具有可读权限,才能使用ls命令

    zhanghuamaodeMacBook-Pro:code zhanghuamao$ sudo chmod a-r test/ ; ls -dl test/;ls -al test/
    d-wx--x--x  4 zhanghuamao  staff  136  2 11 14:22 test/
    ls: : Permission denied
    
    • 可执行权限

    目录要具有可执行权限,才能进入

    zhanghuamaodeMacBook-Pro:code zhanghuamao$ sudo chmod a-x test/
    
    zhanghuamaodeMacBook-Pro:code zhanghuamao$ ls -dl test/ ; cd test/
    drw-r--r--  2 zhanghuamao  staff  68  2 11 11:21 test/
    -bash: cd: test/: Permission denied
    

    3.3 用户ID和组ID

    • 实际用户ID、实际组ID和有效用户ID、有效组ID

    通常,有效用户ID = 实际用户ID,每个文件的所有者有stat中的st_uid指定;
    当执行一个程序文件时,进程的有效用户ID通常就是实际用户ID。但是,当设置了特殊标志时,当执行此文件时,进程的有效用户ID = 文件所有者的用户ID

    • code
    #include "apue.h"
    #include <fcntl.h>
    
    int main(int argc, char const *argv[])
    {
        struct stat buf;
        char *ptr;
    
        if (argc != 2)
        {
            printf("please input a filename\n");
            return 0;
        }
    
        if (access(argv[1], R_OK) < 0 )
            err_ret("access error for %s", argv[1]);
        else
            printf("read access OK\n");
    
        if (open(argv[1], O_RDONLY) < 0)
            err_ret("open error for %s", argv[1]);
        else
            printf("open for reading OK\n");
    
        return 0;
    }
    
    • output
    ckt@ubuntu:~/work/unix/code/chapter4$ cc access_test.c -o access_test
    ckt@ubuntu:~/work/unix/code/chapter4$ ls -l access_test
    -rwxrwxr-x 1 ckt ckt 13419 Feb 12 18:46 access_test
    
    ckt@ubuntu:~/work/unix/code/chapter4$ ls -l /etc/shadow
    -rw-r----- 1 root shadow 1129 Sep 19 23:17 /etc/shadow
    
    ckt@ubuntu:~/work/unix/code/chapter4$ ./access_test /etc/shadow
    access error for /etc/shadow: Permission denied
    open error for /etc/shadow: Permission denied
    
    ckt@ubuntu:~/work/unix/code/chapter4$ sudo chown root access_test
    ckt@ubuntu:~/work/unix/code/chapter4$ sudo chmod u+s access_test
    
    ckt@ubuntu:~/work/unix/code/chapter4$ ls -l access_test
    -rwsrwxr-x 1 root ckt 13419 Feb 12 18:46 access_test
    ckt@ubuntu:~/work/unix/code/chapter4$ ./access_test /etc/shadow
    access error for /etc/shadow: Permission denied
    open for reading OK
    

    3.4 默认权限:umask

    • 查看默认权限

    zhanghuamaodeMacBook-Pro:test zhanghuamao$ umask; umask -S
    0022
    u=rwx,g=rx,o=rx
    

    umask的分数0022指的是“该默认值需要减掉的权限”,umask一共4组数字,第一组是特殊权限用的,后面3组为user、group、other的默认分值

    • 文件和目录的默认权限

    用户建文件时,默认没有可执行权限,即只有r、w这两个选项,默认权限为-rw-rw-rw
    新建文件时默认权限计算方式:(-rwxrw-rw-) - (------w--w) = -rw-r--r--

    zhanghuamaodeMacBook-Pro:test zhanghuamao$ touch test ; ls -l
    total 0
    -rw-r--r--  1 zhanghuamao  staff  0  2 11 15:03 test
    

    用户创建目录时,由于x与是否进入目录有关,因此默认3个权限都开放:-rwxrwxrwx
    新建目录时默认权限计算方式:(-rwxrwxrwx) - (------w--w) = -rwxr-xr-x

    zhanghuamaodeMacBook-Pro:test zhanghuamao$ mkdir dir; ls -l
    total 0
    drwxr-xr-x  2 zhanghuamao  staff  68  2 11 15:06 dir
    -rw-r--r--  1 zhanghuamao  staff   0  2 11 15:03 test
    

    3.5 umask函数

    • 函数原型
      mode_t umask(mode_t mask); , 其中的参数mask的值定义在/usr/include/sys/stat.h中:
    #define S_IRUSR __S_IREAD   /* Read by owner.  */
    #define S_IWUSR __S_IWRITE  /* Write by owner.  */
    #define S_IXUSR __S_IEXEC   /* Execute by owner.  */
    /* Read, write, and execute by owner.  */
    #define S_IRWXU (__S_IREAD|__S_IWRITE|__S_IEXEC)
    
    #define S_IRGRP (S_IRUSR >> 3)  /* Read by group.  */
    #define S_IWGRP (S_IWUSR >> 3)  /* Write by group.  */
    #define S_IXGRP (S_IXUSR >> 3)  /* Execute by group.  */
    /* Read, write, and execute by group.  */
    #define S_IRWXG (S_IRWXU >> 3)
    
    #define S_IROTH (S_IRGRP >> 3)  /* Read by others.  */
    #define S_IWOTH (S_IWGRP >> 3)  /* Write by others.  */
    #define S_IXOTH (S_IXGRP >> 3)  /* Execute by others.  */
    /* Read, write, and execute by others.  */
    #define S_IRWXO (S_IRWXG >> 3)
    
    • code
    #include "apue.h"
    #include <fcntl.h>
    
    #define RWRWRW (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
    
    int main(int argc, char const *argv[])
    {
        umask(0);
        if (creat("test", RWRWRW) < 0 )
            err_sys("create error for test");
        umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
        if (creat("test2", RWRWRW) < 0 )
            err_sys("create error for test2");
        return 0;
    }
    
    • output
    ckt@ubuntu:~/work/unix/code/chapter4$ cc umask_test.c -o umask_test
    
    ckt@ubuntu:~/work/unix/code/chapter4$ umask 
    0002
    
    ckt@ubuntu:~/work/unix/code/chapter4$ ./umask_test
    ckt@ubuntu:~/work/unix/code/chapter4$ ls -l test*
    -rw-rw-rw- 1 ckt ckt 0 Feb 12 21:53 test
    -rw------- 1 ckt ckt 0 Feb 12 21:53 test2
    
    ckt@ubuntu:~/work/unix/code/chapter4$ umask
    0002
    

    3.6 chmod函数

    • code
    #include "apue.h"
    
    int main(int argc, char const *argv[])
    {
        struct stat statbuf;
        if (stat("test", &statbuf) < 0 )
            err_sys("stat error for test");
        
        if (chmod("test", (statbuf.st_mode & ~S_IWGRP) |  S_IXGRP) < 0 )
            err_sys("chmod error for test");
    
        if (chmod("test2", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) < 0 )
            err_sys("chmod error for test2");
    
        return 0;
    }
    
    • output
    ckt@ubuntu:~/work/unix/code/chapter4$ ls -l test*
    -rw-rw-rw- 1 ckt ckt 0 Feb 13 00:17 test
    -rw------- 1 ckt ckt 0 Feb 13 00:17 test2
    
    ckt@ubuntu:~/work/unix/code/chapter4$ cc chmod_test.c -o chmod_test
    ckt@ubuntu:~/work/unix/code/chapter4$ ./chmod_test
    ckt@ubuntu:~/work/unix/code/chapter4$ ls -l test*
    -rw-r-xrw- 1 ckt ckt 0 Feb 13 00:17 test
    -rw-rw---- 1 ckt ckt 0 Feb 13 00:17 test2
    

    3.7 chown函数

    • code
    #include "apue.h"
    
    int main(int argc, char const *argv[])
    {
        if (chown("test", getuid(), getgid()) < 0 )
            err_sys("chmod error for test");
    
        return 0;
    }
    
    • output
    ckt@ubuntu:~/work/unix/code/chapter4$ cc chown_test.c -o chown_test
    ckt@ubuntu:~/work/unix/code/chapter4$ ls -l test
    -rw------- 1 ckt ckt 0 Feb 13 00:17 test
    
    ckt@ubuntu:~/work/unix/code/chapter4$ sudo ./chown_test
    ckt@ubuntu:~/work/unix/code/chapter4$ ls -l test
    -rw------- 1 root root 0 Feb 13 00:17 test
    

    4. 文件系统

    4.1 硬链接和软链接对比

    在link目录下,使用link命令给test目录下的file文件创建一个硬链接hard_link,file和hard_link的inode相同,都为1000760

    zhanghuamaodeMacBook-Pro:link zhanghuamao$ link ../test/file hard_link
    zhanghuamaodeMacBook-Pro:link zhanghuamao$ ls -li hard_link ../test/file 
    1000760 -rw-r--r--  2 zhanghuamao  staff  0  2 12 11:36 ../test/file
    1000760 -rw-r--r--  2 zhanghuamao  staff  0  2 12 11:36 hard_link
    

    使用ls -li查看link和test目录的inode号,分别为1000766、100068

    zhanghuamaodeMacBook-Pro:code zhanghuamao$ ls -li
    1000766 drwxr-xr-x   2 zhanghuamao  staff   68  2 12 11:37 link
    1000688 drwxr-xr-x   3 zhanghuamao  staff  102  2 12 11:36 test
    

    再使用ln -s命令给file文件创建一个软链接soft_link,查看soft_link的inode号为1000805,和file的inode号不一样。

    zhanghuamaodeMacBook-Pro:link zhanghuamao$ ln -s ../test/file soft_link
    zhanghuamaodeMacBook-Pro:link zhanghuamao$ ls -il ../test/file soft_link
    1000760 -rw-r--r--  2 zhanghuamao  staff   0  2 12 11:36 ../test/file
    1000805 lrwxr-xr-x  1 zhanghuamao  staff  12  2 12 11:40 soft_link -> ../test/
    

    往hard_link文件中添加内容"add by hard link",使用cat命令查看soft_link和file文件,内容都同步更新了。

    zhanghuamaodeMacBook-Pro:link zhanghuamao$ cat soft_link ../test/file 
    add by hard link
    add by hard link
    

    删除file文件,再次使用cat命令查看soft_link和hard_link文件,soft_link提示"No such file or directory",而hard_link文件仍然存在。

    zhanghuamaodeMacBook-Pro:link zhanghuamao$ rm ../test/file 
    zhanghuamaodeMacBook-Pro:link zhanghuamao$ cat soft_link hard_link 
    cat: soft_link: No such file or directory
    add by hard link
    

    创建硬链接后,inode和bloack data示意图


    硬链接

    当删除file文件时,hard_link仍然可以通过编号为1000760的inode访问文件内容

    硬链接 - 删除file文件后

    创建软链接后,inode和bloack data示意图

    软链接

    当删除file文件后,soft_link无法再通过test目录的inode号访问file文件

    软链接 - 删除file文件

    4.2 获取文件的硬链接

    • code
    #include "../inc/apue.h"
    
    int main(int argc, char const *argv[])
    {
        struct stat buf;
        char *ptr;
    
        if (argc != 2)
        {
            printf("please input a filename\n");
            return 0;
        }
    
        if (lstat(argv[1], &buf) < 0 )
            err_ret("lstat error");
    
        printf("The hard link count of %s : %d\n", argv[1], buf.st_nlink);
    
        return 0;
    }
    
    • output

    先ls -il查看hard_link文件的链接数为3

    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ls -il ../link/hard_link*
    1005313 -rw-r--r--  3 zhanghuamao  staff  0  2 12 16:20 ../link/hard_link
    1005313 -rw-r--r--  3 zhanghuamao  staff  0  2 12 16:20 ../link/hard_link1
    1005313 -rw-r--r--  3 zhanghuamao  staff  0  2 12 16:20 ../link/hard_link2
    

    运行link_text程序查看hard_link文件的链接数,和ls -il得到的结果一致,都为3

    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ cc link_text.c -o link_text
    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ./link_text ../link/hard_link
    The hard link count of ../link/hard_link : 3
    

    4.3 link函数

    • code
    #include "../inc/apue.h"
    
    int main(int argc, char const *argv[])
    {
        struct stat buf;
        char *ptr;
    
        if (argc != 3)
        {
            printf("please input a filename\n");
            return 0;
        }
    
        link(argv[1], argv[2]);
    
        return 0;
    }
    
    • output

    运行程序my_link创建my_link.c的硬链接文件my_link_hard_link.txt

    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ cc my_link.c -o my_link
    
    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ls
    get_file_type   link_text   my_link     stat_test
    get_file_type.c link_text.c my_link.c   stat_test.c
    
    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ./my_link my_link.c my_link_hard_link.txt
    

    运行完成后使用ls -il查看,my_link.c和my_link_hard_link.txt的inode号一样都为1006798

    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ls -il my*
    1006809 -rwxr-xr-x  1 zhanghuamao  staff  13596  2 12 16:56 my_link
    1006798 -rw-r--r--@ 2 zhanghuamao  staff    275  2 12 16:55 my_link.c
    1006798 -rw-r--r--@ 2 zhanghuamao  staff    275  2 12 16:55 my_link_hard_link.txt
    

    4.4 unlink函数

    • code
    #include "../inc/apue.h"
    
    int main(int argc, char const *argv[])
    {
        struct stat buf;
        char *ptr;
    
        if (argc != 2)
        {
            printf("please input a filename\n");
            return 0;
        }
    
        unlink(argv[1]);
    
        return 0;
    }
    
    • output

    运行程序my_unlink取消掉之前创建的my_link_hard_link.txt

    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ cc my_unlink.c -o my_unlink
    
    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ./my_unlink my_link_hard_link.txt 
    

    已经没有my_link_hard_link.txt 这支文件了

    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ls -il my*
    1006809 -rwxr-xr-x  1 zhanghuamao  staff  13596  2 12 16:56 my_link
    1006798 -rw-r--r--@ 1 zhanghuamao  staff    210  2 12 17:05 my_link.c
    1006904 -rwxr-xr-x  1 zhanghuamao  staff  13596  2 12 17:06 my_unlink
    1006865 -rw-r--r--@ 1 zhanghuamao  staff    203  2 12 17:06 my_unlink.c
    

    4.5 rename函数

    • code
    #include "../inc/apue.h"
    
    int main(int argc, char const *argv[])
    {
        struct stat buf;
        char *ptr;
    
        if (argc != 3)
        {
            printf("please input a filename\n");
            return 0;
        }
    
        rename(argv[1], argv[2]);
    
        return 0;
    }
    
    • output

    运行程序my_mv创建硬链接前,先查看当前已使用inode个数为793518

    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ cc my_mv.c -o my_mv
    
    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ df .
    Filesystem 512-blocks     Used Available Capacity iused      ifree %iused  Mounted on
    /dev/disk1  487686144 65661544 421512600    14%  793518 4294173761    0%   /
    

    运行程序my_mv创建my_mv.c的硬链接my_mv_rename.txt,查看它们的inode号都为1007929,并且已使用inode个数和创建硬链接前一样。

    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ./my_mv my_mv.c my_mv_rename.txt
    
    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ df .
    Filesystem 512-blocks     Used Available Capacity iused      ifree %iused  Mounted on
    /dev/disk1  487686144 65663336 421510808    14%  793518 4294173761    0%   /
    
    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ls -il my_m*
    1007936 -rwxr-xr-x  1 zhanghuamao  staff  13596  2 12 17:37 my_mv
        1007929 -rwxr-xr-x  1 zhanghuamao  staff    212  2 12 17:37 my_mv.c
    1007929 -rwxr-xr-x  1 zhanghuamao  staff    212  2 12 17:37 my_mv_rename.txt
    

    4.6 symlink函数

    • code
    #include "../inc/apue.h"
    
    int main(int argc, char const *argv[])
    {
        struct stat buf;
        char *ptr;
    
        if (argc != 3)
        {
            printf("please input a filename\n");
            return 0;
        }
    
        symlink(argv[1], argv[2]);
    
        return 0;
    }
    
    • output

    在运行程序my_ln创建软链接前,先使用df命令查看当前已用inode个数为793532

    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ cc my_ln.c -o my_ln 
    
    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ df .
    Filesystem 512-blocks     Used Available Capacity iused      ifree %iused  Mounted on
    /dev/disk1  487686144 65664040 421510104    14%  793532 4294173747    0%   /
    

    运行程序my_ln创建my_ln.c的软链接my_ln_soft_link.txt,查看它们的inode号分别是1008145和1008163

    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ./my_ln my_ln.c my_ln_soft_link.txt
    
    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ls -il my_ln*
    1008156 -rwxr-xr-x  1 zhanghuamao  staff  13604  2 12 17:50 my_ln
    1008145 -rw-r--r--@ 1 zhanghuamao  staff    213  2 12 17:49 my_ln.c
    1008163 lrwxr-xr-x  1 zhanghuamao  staff      7  2 12 17:51 my_ln_soft_link.txt -> my_ln.c
    

    再次使用df命令查看当前已用inode个数为793533,比运行程序my_ln前,少了一个inode号

    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ df .
    Filesystem 512-blocks     Used Available Capacity iused      ifree %iused  Mounted on
    /dev/disk1  487686144 65663920 421510224    14%  793533 4294173746    0%   /
    

    将my_ln.c删除,再去cat my_ln_soft_link.txt,提示错误"cat: my_ln_soft_link.txt: No such file or directory"

    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ rm my_ln.c ; cat my_ln_soft_link.txt
    cat: my_ln_soft_link.txt: No such file or directory
    

    4.7 时间参数

    Unix中一共有3个时间参数,这3个值被记录在stat成员变量中:

     struct timespec st_atimespec;  /* time of last access */
     struct timespec st_mtimespec;  /* time of last data modification */
     struct timespec st_ctimespec;  /* time of last file status change */
    
    • modification time(mtime)
      当修改文件内容时,mtime会更新,使用ls -l命令查看的时间就是mtime
    ckt@ubuntu:~/work/unix/code/chapter4$ ls -l ../chapter2/limits_test.c 
    -rwxr--r-- 1 ckt ckt 179 Jan 15 22:10 ../chapter2/limits_test.c
    
    • acess time(atime)
      当文件内容被取用时,就会更新atime。例如,使用cat去读取文件时。
      使用命令ls -l --time=atime可以查看atime
    ckt@ubuntu:~/work/unix/code/chapter4$ cat ../chapter2/limits_test.c 
    cat内容省略
    ckt@ubuntu:~/work/unix/code/chapter4$ls -l ../chapter2/limits_test.c
    -rwxr--r-- 1 ckt ckt 179 Jan 15 22:10 ../chapter2/limits_test.c
    
    ckt@ubuntu:~/work/unix/code/chapter4$ ls -l --time=atime ../chapter2/limits_test.c 
    -rwxr--r-- 1 ckt ckt 179 Feb 13 01:00 ../chapter2/limits_test.c
    
    ckt@ubuntu:~/work/unix/code/chapter4$ date
    Mon Feb 13 01:01:12 PST 2017
    
    • status time(ctime)
      当文件的状态改变时,就会更新这个时间,例如:权限与属性被更改了
      使用命令ls -l --time=ctime可以查看ctime
    ckt@ubuntu:~/work/unix/code/chapter4$ chmod 644 ../chapter2/limits_test.c 
    ckt@ubuntu:~/work/unix/code/chapter4$ ls -l --time=ctime ../chapter2/limits_test.c 
    -rw-r--r-- 1 ckt ckt 179 Feb 13 01:03 ../chapter2/limits_test.c
    

    4.8 打印设备ID

    • code
    #include "apue.h"
    #include <sys/sysmacros.h>
    
    int main(int argc, char const *argv[])
    {
        struct stat buf;
    
        if (argc != 2)
        {
            printf("please input a filename\n");
            return 0;
        }
    
        if (lstat(argv[1], &buf) < 0 )
            err_ret("lstat error");
    
        printf("dev = %d / %d ", major(buf.st_dev), minor(buf.st_dev));
        
        if (S_ISCHR(buf.st_mode) || S_ISBLK(buf.st_mode))
        {
            printf(", rdev = %d / %d ", major(buf.st_rdev), minor(buf.st_rdev));
        }
    
        printf("\n");
        return 0;
    }
    
    • output
    ckt@ubuntu:~/work/unix/code/chapter4$ cc dev_test.c -o dev_test
    ckt@ubuntu:~/work/unix/code/chapter4$ ./dev_test /dev/tty1
    dev = 0 / 5 , rdev = 4 / 1 
    ckt@ubuntu:~/work/unix/code/chapter4$ ./dev_test dev_test
    dev = 8 / 17 
    

    5. 目录操作

    5.1 mkdir函数

    • code
    #include "apue.h"
    
    #define RWXRXRX (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
    
    int main(int argc, char const *argv[])
    {
        if (argc != 2)
        {
            printf("please input a filename\n");
            return 0;
        }
    
        if (mkdir(argv[1], RWXRXRX) < 0 )
            err_ret("mkdir error");
        return 0;
    }
    
    • output
    ckt@ubuntu:~/work/unix/code/chapter4$ cc mkdir_test.c -o mkdir_test
    ckt@ubuntu:~/work/unix/code/chapter4$ ./mkdir_test 222
    ckt@ubuntu:~/work/unix/code/chapter4$ ls -dl 222
    drwxr-xr-x 2 ckt ckt 4096 Feb 15 01:14 222
    

    5.2 rmdir函数

    • code
    #include "apue.h"
    
    int main(int argc, char const *argv[])
    {
        if (argc != 2)
        {
            printf("please input a filename\n");
            return 0;
        }
    
        if (rmdir(argv[1]) < 0 )
            err_ret("rmdir error");
        return 0;
    }
    
    • output
    ckt@ubuntu:~/work/unix/code/chapter4$ cc rmdir_test.c -o rmdir_test
    ckt@ubuntu:~/work/unix/code/chapter4$ ./rmdir_test 222/
    ckt@ubuntu:~/work/unix/code/chapter4$ ls -dl 222
    ls: cannot access 222: No such file or directory
    

    5.3 chdir函数

    • code
    #include "apue.h"
    
    int main(int argc, char const *argv[])
    {
        if (chdir("/home") < 0 )
            err_ret("chdir error");
    
        printf("chdir to /home succeeded\n");
    
        printf("current path = %s\n", get_current_dir_name());
        return 0;
    }
    
    • output
      运行程序chdir_test后,shell显示的当前目录并没有改变,这是因为每个程序运行在独立的进程中,shell的当前工作目录并不会随着程序调用chdir而改变。但是,chdir_test程序通过调用get_current_dir_name函数,可以将当前目录名称打印出来,由此可以证明chdir已经生效
    ckt@ubuntu:~/work/unix/code/chapter4$ cc chdir_test.c -o chdir_test
    
    ckt@ubuntu:~/work/unix/code/chapter4$ ./chdir_test
    chdir to /home succeeded
    current path = /home
    

    5.4 读目录

    • code
    #include "../inc/apue.h"
    #include <dirent.h>
    
    int main(int argc, char const *argv[])
    {
        DIR *dirp;
        struct dirent *dp;
    
        dirp = opendir("../");
    
        if (dirp == NULL)
            return 0;
    
        while ((dp = readdir(dirp)) != NULL)
        {
            printf("%s\n", dp->d_name);
        }
    
        return 0;
    }
    
    • output
    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ cc readdir_test.c -o readdir_test
    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ./readdir_test 
    .
    ..
    chapter3
    chapter4
    file1
    file2
    inc
    link
    test
    
    zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ls -l ../
    total 0
    drwxr-xr-x  17 zhanghuamao  staff  578  1 22 21:55 chapter3
    drwxr-xr-x  21 zhanghuamao  staff  714  2 15 23:18 chapter4
    -rw-r--r--   1 zhanghuamao  staff    0  2 15 23:01 file1
    -rw-r--r--   1 zhanghuamao  staff    0  2 15 23:01 file2
    drwxr-xr-x   4 zhanghuamao  staff  136  1 21 10:06 inc
    drwxr-xr-x   8 zhanghuamao  staff  272  2 12 16:25 link
    drwxr-xr-x   2 zhanghuamao  staff   68  2 12 11:43 test
    

    参考

    相关文章

      网友评论

        本文标题:从零开始UNIX环境高级编程(4):文件和目录

        本文链接:https://www.haomeiwen.com/subject/eygwittx.html