文件和目录

2020-06-11  本文已影响0人  yuq329

文件和目录

函数stat、fstat、fstatat和lstat

#include<sys/stat.h>
int stat(const char *restrict pathname, struct stat *restrict buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *restrict pathname, struct stat *restrict buf);
int fstatat(int fd, const char *restrict pathname, struct stat *restrict buf, int flag);
struct stat {
    dev_t           st_dev;         /* [XSI] ID of device containing file */
    ino_t           st_ino;         /* [XSI] File serial number */
    mode_t          st_mode;        /* [XSI] Mode of file (see below) */
    nlink_t         st_nlink;       /* [XSI] Number of hard links */
    uid_t           st_uid;         /* [XSI] User ID of the file */
    gid_t           st_gid;         /* [XSI] Group ID of the file */
    dev_t           st_rdev;        /* [XSI] Device ID */
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
    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 */
#else
    time_t          st_atime;       /* [XSI] Time of last access */
    long            st_atimensec;   /* nsec of last access */
    time_t          st_mtime;       /* [XSI] Last data modification time */
    long            st_mtimensec;   /* last data modification nsec */
    time_t          st_ctime;       /* [XSI] Time of last status change */
    long            st_ctimensec;   /* nsec of last status change */
#endif
    off_t           st_size;        /* [XSI] file size, in bytes */
    blkcnt_t        st_blocks;      /* [XSI] blocks allocated for file */
    blksize_t       st_blksize;     /* [XSI] 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! */
};

文件类型

#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 管道或FIFIO*/
#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 套接字*/
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
#define S_ISWHT(m)      (((m) & S_IFMT) == S_IFWHT)     /* OBSOLETE: whiteout */
#endif
#define S_TYPEISMQ(buf)         (0)     /* Test for a message queue 消息队列 */
#define S_TYPEISSEM(buf)        (0)     /* Test for a semaphore 信号量*/
#define S_TYPEISSHM(buf)        (0)     /* Test for a shared memory object 共享存储对象*/
#include <apue.h>
#include<error.h>

int main(int argc, char *argv[]) {
    int i;
    struct stat buf;
    char *ptr;
    for (i = 1; i < argc; i++) {
        printf("%s: ", argv[i]);
        if (lstat(argv[i], &buf) < 0) {
            err_ret("lstat error");
            continue;
        }
        if (S_ISREG(buf.st_mode))
            ptr = "regular";
        else if (S_ISDIR(buf.st_mode))
            ptr = "directory";
        else if (S_ISCHR(buf.st_mode))
            ptr = "charactor special";
        else if (S_ISBLK(buf.st_mode))
            ptr = "block special";
        else if (S_ISFIFO(buf.st_mode))
            ptr = "fifo";
        else if (S_ISLNK(buf.st_mode))
            ptr = "symbolic link";
        else if (S_ISSOCK(buf.st_mode))
            ptr = "socket";
        else
            ptr = "** unknown mode **";
        printf("%s\n", ptr);

    }
    exit(0);
}
$ ./filedir /etc/passwd /etc /dev/tty /dev/disk4 /dev/fd
/etc/passwd: regular
/etc: symbolic link
/dev/tty: charactor special
/dev/disk4: block special
/dev/fd: directory

设置用户ID以及设置组ID

文件访问权限

新文件和目录的所有权

函数access和faccessat

函数umask

函数chmod、fchmod和fchmodat

粘着位

函数chown、fchown、fchownat和lchown

文件长度

文件截断

文件系统

函数link、linkat、unlink、unlinkat和remove

函数rename和renameat

符号链接

创建和读取符号链接

文件的时间

函数futimens、utimensat和utimes

```c
#include <apue.h>
#include <error.h>
#include <fcntl.h>

int main(int argc, char *argv[]) {
    int i, fd;
    struct stat statbuf;
    struct timespec times[2];
    for (i = 1; i < argc; i++) {
        if (stat(argv[i], &statbuf) < 0) {
            err_ret("%s: stat error", argv[i]);
            continue;
        }
        if ((fd = open(argv[i], O_RDWR | O_TRUNC)) < 0) {
            err_ret("%s: open error", argv[i]);
            continue;
        }
        //我的系统中stat返回的time_t结构,根据需要调整
        times[0].tv_sec = statbuf.st_atime;
        times[1].tv_sec = statbuf.st_mtime;
        if (futimens(fd, times) < 0) {
            err_ret("%s: futimens error", argv[i]);
        }
        close(fd);
    }
}
```

函数mkdir、mkdirat和rmdir

读目录

函数chdir、fchdir和getcwd

设备特殊文件

文件访问权限位小结

文件访问权限小结

习题

  1. stat替换lstat函数

    1. stat总是跟随符号链接,不会显示文件类型是符号链接
    2. 访问不存在的文件会出错
  2. umask 777

    1. 屏蔽文件所有访问权限,就如chmod 777 打开文件所有权限
  3. 用户关闭自己拥有文件的用户读权限之后,将不能访问自己的文件

  4. opencreat创建已经存在的文件,将会怎么样?

    1. 已存在的文件访问权限不变
    2. 但文件被截断
  5. 目录和符号链接的长度st_size是否可以为0

    1. 普通文件的长度可以为0
    2. 目录至少包含...两项,长度不为0
    3. 符号链接的长度是其路径名包含的字符数,路径长度至少为1,长度也不为0
  6. 编写一个类似cp(1)的程序,它复制包含空洞的文件,但不将字节0写到输出文件中去。
    原文链接

    #include <stdio.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <string.h>
    #include <stdlib.h>
    #include <sys/stat.h>
    
    #define BUF_SIZE 4096
    
    int my_cp(const char *file1, const char *file2)
    {
        int fd1, fd2;
        char buffer[BUF_SIZE];
        int res, current_position = 0, byte_count =0, have_holes = 0;
        struct stat st;
    
        fd1 = open(file1, O_RDWR);
        if(-1 == fd1){
            perror("open file1 faild");
            return -1;
        }
    
        if(fstat ( fd1, &st) !=0)
            perror("fstat");
        else{
            if (S_ISREG(st.st_mode) && st.st_size > 512 * st.st_blocks) {
                have_holes = 1;
                printf("%s is a sparse-block file!\n", file1);
            } else{ 
                have_holes = 0;
                printf("%s is not a sparse-block file!\n", file1);
            }
        }
    
        fd2 = open(file2, O_RDWR | O_APPEND | O_CREAT | O_TRUNC, 0666);
        if ( -1 == fd2) {
            perror ("open file2 faild");
            return -1;
        }
    
        memset(buffer, '\0', BUF_SIZE);
        res = read(fd1, buffer, BUF_SIZE);//返回读到的字节数
        if ( -1 == res) {
            perror ("file1 read error");
            return -1;
        }
    
        if(have_holes){
            byte_count =0;
            for (current_position = 0; current_position < res; current_position ++) {
    
                if (0 != buffer[current_position] )
                {
                        buffer[byte_count] = buffer[current_position];
                        byte_count ++;
                }
            }
        }else
            byte_count = res;
    
        res = write(fd2, buffer, byte_count);
        if ( -1 == res){
            perror( " file2 write error");
            return -1;
        }
    
        close(fd1);
        close(fd2);
    }
    
    
    int main(int argc, char * argv[])
    {
        if (3 != argc){
            printf("usage error : ./a.out file1 file2\n");
            return -1;
        }
        int res = my_cp(argv[1], argv[2]);
        if ( -1 == res) {
            perror (" my_cp error");
            return -1;
        }
    
        exit(0);
    }
    
  7. 在没有更改umask的前提下,内核拷贝的文件权限与原文件权限不一致,为什么?

    1. 它们属于不同的进程,拥有的umask不是同一个
  8. df(1)命令和du(1)命令检查空闲的磁盘空间的区别

    1. du命令检查需要文件名或目录名,当unlink没有返回时,文件名没有了,但是内容还没有清除,du命令不会计算这部分内存
    2. 此时只能使用df命令查看文件系统中实际可用的空闲空间
  9. unlink函数会修改文件状态更改时间,这是怎样发生的?

    1. 如果删除的链接不是最后一个链接,此时修改文件状态更改时间
    2. 如果删除的是最后一个链接,此时文件将被物理删除,此时修改文件状态更改时间没有意义
  10. 系统对可打开文件数的限制对myftw函数有什么影响?

    1. 每次降一级就要使用另一个文件描述符,所以进程可以打开的文件数限制了我们可以遍历的文件系统树的深度。
    2. SUSXSI扩展中说明ftw允许调用者指定使用的描述符数,这隐含着可以关闭描述符并且重用它们
  11. myftw函数从不改变其目录,如果每次访问下一个遇到的目录,使用chdir修改当前工作目录到遇到的目录,这样可以使用文件名而非路径调用lstat,访问结束后在利用chdir("..")修改回工作目录,这样会更快吗?

  12. 每个进程都有一个根目录用于解析绝对路径名,可以通过chroot函数改变根目录。这个函数什么时候用?

  13. 如何只设置两个时间值中的一个来使用utimes函数

  14. 可以看一看

上一篇 下一篇

猜你喜欢

热点阅读