open

打开一个文件

头文件:
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
原型:
    int open(const char *pathname, int flags);
    int open(const char *pathname, int flags, mode_t mode);
参数:
    char *pathname:文件路径+文件名;
    int flags:文件的打开方式。
        O_RDONLY     只读
        O_WRONLY     只写
        O_RDWR       读写
    ----以上三种必须包含一种-----
        O_APPEND     追加
        O_CREAT      创建
        O_TRUNC      清空
        “w”: O_WRONLY|O_CREAT|O_TRUNC  //以写的方式打开目标文件,如果目标文件不存在则创建,如果存在则清空;
    mode_t mode:文件的八进制权限,0777、0664 ;
        如果 flags 包含了 O_CREAT;必须要有mode参数,否则会忽略O_CREAT;
返回值:
    成功,返回文件描述符;
    失败,返回-1,更新errno;
例程:
    int fd = open("./2.png", O_WRONLY|O_CREAT|O_TRUNC, 0664);
    if(fd < 0)
    {
        perror("open");
        fprintf(stderr, "%d\n", __LINE__);
        return -1;
    }

close

关闭一个文件

头文件:
    #include <unistd.h>
原型:
    int close(int fd);
参数:
    int fd:指定要关闭的文件描述符;
返回值:
    成功,返回0;
    失败,返回-1,更新errno;
例程:
    close(fd);

write

将数据写入到文件中

头文件:
    #include <unistd.h>
原型:
    ssize_t write(int fd, const void *buf, size_t count);
参数:
    int fd:文件描述符;
    void *buf:存储着要写入到文件中的数据的首地址,可以是任意类型;
    size_t count:要写入的数据大小,以字节为单位;
返回值:
    成功,返回写入的数据个数;
    失败,返回-1,更新errno;
例程:
    char buf[N] = "hello world";
    if(write(fd,buf,strlen(buf)) < 0)
    {
        perror("write");
        return -1;
    }

read

从文件中读取数据

头文件:
    #include <unistd.h>
原型:
    ssize_t read(int fd, void *buf, size_t count);
参数:
    int fd:文件描述符;
    void *buf:存储读取到的数据,可以是任意类型;
    size_t count:要读取的数据大小,以字节为单位;
返回值:
    成功,返回读取到的数据个数;
        0,表示读取到文件结尾;
    失败,返回-1,更新errno;
例程:
    int fd = open("./open.txt", O_RDONLY);
    char c = 0;
    while(read(fd , &c, 1)!=0)
    {   
        printf("%c",c);
    }

lseek

偏移文件指针,并返回设置后的文件指针相对于文件开头的偏移量

头文件:
    #include <sys/types.h>
    #include <unistd.h>
原型:
    off_t lseek(int fd, off_t offset, int whence);
参数:
    int fd:文件描述符;
    long offset:相对于参数whence的偏移量;
    int whence:
        SEEK_SET:文件开头位置。
        SEEK_CUR:文件当前位置;
        SEEK_END:文件结尾位置;
返回值:
    成功,返回设置后的文件指针相对于文件开头的偏移量;
    失败,返回(off_t)-1,更新errno;
例程:
计算文件大小:
    off_t size = lseek(fd, 0, SEEK_END); 
相当于:
    fseek(fp, 0, SEEK_END);
    long size = ftell(fp);

umask

修改文件权限掩码(文件创建的真正权限是mode & ~umask)

头文件:
    #include <sys/types.h>
    #include <sys/stat.h>
原型:
    mode_t umask(mode_t mask);
例程:
    umaks(0);//保持文件原有权限
0777 & ~0002 
    = 111 111 111 & ~000 000 010
    = 111 111 111 & 111 111 101
    = 111 111 101 --> 0775

应用例程1

要求用read, write拷贝一张图片,例如将2.png拷贝成3.png

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int copy_picture(int fd_src, int fd_dest)
{
    //循环读一次写一次
    char s[100] = "";
    int ret = 0;
    while(1)
    {
        bzero(s, sizeof(s));
        ret = read(fd_src, s, 100);
        if(ret < 0)
        {
            perror("read");
            return -1;
        }
        else if(0 == ret)
        {
            printf("*****文件读取完毕*****\n");
            break;
        }
        printf("%d\n", ret);
        if(write(fd_dest, s, ret) < 0)
        {
            perror("write");
            return -2;
        }
    }
    return 0;
}
int main(int argc, const char *argv[])
{
    //以读的方式打开原文件
    int fd_src = open("./1.png", O_RDONLY);
    if(fd_src < 0)
    {
        perror("open");
        fprintf(stderr, "%d\n", __LINE__);
        return -1;
    }
    //以写的方式打开目标文件,如果目标文件不存在创建,如果存在则清空
    int fd_dest = open("./2.png", O_WRONLY|O_CREAT|O_TRUNC, 0664);
    if(fd_dest < 0)
    {
        perror("open");
        fprintf(stderr, "%d\n", __LINE__);
        return -1;
    }
    //拷贝 read write
    copy_picture(fd_src, fd_dest);
    //关闭两个文件描述符
    close(fd_src);
    close(fd_dest);
    return 0;
}

stat

获取文件属性

头文件:
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
原型:
    int stat(const char *path, struct stat *buf);
参数:
    char *path:文件的路径文件名;
    struct stat *buf:存储获取到的文件属性;
    struct stat {
        dev_t     st_dev;     /* ID of device containing file */
        ino_t     st_ino;     /* inode number */ inode号;
        mode_t    st_mode;    /* protection */ 文件类型+文件权限;
        nlink_t   st_nlink;   /* number of hard links */ 硬链接数;
        uid_t     st_uid;     /* user ID of owner */ 文件所属用户的uid;
        gid_t     st_gid;     /* group ID of owner */ 文件所属用户组的gid;
        dev_t     st_rdev;    /* device ID (if special file) */
        off_t     st_size;    /* total size, in bytes */ 文件大小,以字节为单位;
        blksize_t st_blksize; /* blocksize for filesystem 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 */ 最后一次改变状态的时间;
    };
返回值:
    成功,返回0;
    失败,返回-1,更新errno;
例程:
    struct stat buf;
    if(stat(argv[1], &buf) < 0)
    {
        perror("stat");
        return -1;
    }

提取文件的权限

st_mode:是一个32位无符号的整形变量,其中低9位[0, 8],代表文件的权限;

用 st_mode & 相应的权限

st_mode: 0100664
    664 --> 110 110 100
    &       100 000 000
    ---------------------
            100 000 000 ---->0400     说明当前用户有可读权限 ---> r;

    664 --> 110 110 100
    &       001 000 000
    ---------------------
            000 000 000

对应权限的宏

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
例程:
void get_filemode(mode_t mode)
{
    int i;
    mode_t m;
    for(i=8;i>=0;i--)
    {
        m = mode & 1<<i;
        if(m == 0)
        {
            putchar('-');
            continue;
        }
        switch(i%3)
        {
            case 0:
                putchar('x');
                break;
            case 1:
                putchar('w');
                break;
            case 2:
                putchar('r');
                break;
        }
    }
}

提取文件的类型

7种文件类型:bcd-lsp

功能:通过宏函数来判断
    b    S_ISBLK(m)  block device?
    c    S_ISCHR(m)  character device?
    d    S_ISDIR(m)  directory?
    -    S_ISREG(m)  is it a regular file?
    l    S_ISLNK(m)  symbolic link? 
    s    S_ISSOCK(m) socket?
    p    S_ISFIFO(m) FIFO (named pipe)?
参数:
    m:文件属性结构体struct stat *buf 中的 mode_t st_mode;
返回值:
    1,代表是该类型文件;
    0,代表不是该类型的文件;
例程:
    void getType(mode_t m)
    {
        if(S_ISREG(m))
            putchar('-');
        else if(S_ISDIR(m))
            putchar('d');
        else if(S_ISCHR(m))
            putchar('c');
        else if(S_ISBLK(m))
            putchar('b');
        else if(S_ISFIFO(m))
            putchar('p');
        else if(S_ISLNK(m))  
            putchar('l');
        else if(S_ISSOCK(m))
            putchar('s');
    }

st_mode:是一个32位无符号的整形变量,其中低16位到低13位[12, 15],代表文件的类型;

宏 S_IFMT 0170000

通过 st_mode & S_IFMT 提取出4bit 后与下列宏比较,如果相等,则是对应类型的文件。
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

例程:
void getType(mode_t m)
{
    switch (m & S_IFMT) {
    case S_IFBLK:  printf("b");     break;
    case S_IFCHR:  printf("c");     break;
    case S_IFDIR:  printf("d");     break;
    case S_IFIFO:  printf("p");     break;
    case S_IFLNK:  printf("l");     break;
    case S_IFREG:  printf("-");     break;
    case S_IFSOCK: printf("s");     break;
    default:       printf("unknown?\n");   break;
    }
}

获取文件所属用户信息

getpwuid

通过 struct stat 结构体中的 uid_t st_uid 成员变量,获取文件所属用户信息

头文件:
    #include <sys/types.h>
    #include <pwd.h>
原型:
    struct passwd *getpwuid(uid_t uid);
参数:
    uid_t uid:文件所属用户的id;
返回值:
    成功,返回存储文件所属用户信息的结构体 struct passwd * ;
    struct passwd {
        char   *pw_name;       /* username */
        char   *pw_passwd;     /* user password */
        uid_t   pw_uid;        /* user ID */
        gid_t   pw_gid;        /* group ID */
        char   *pw_gecos;      /* user information */
        char   *pw_dir;        /* home directory */
        char   *pw_shell;      /* shell program */
    };
    失败,返回NULL,更新errno;
例程:
    //提取文件所属用户的名字
    char* getUsrName(char*name, uid_t uid)
    {
        struct passwd* pwd = NULL;
        pwd = getpwuid(uid);
        if(NULL == pwd)
        {   
            perror("getpwuid");
            return NULL;
        }   
        strcpy(name, pwd->pw_name);
        return name;
    }

获取文件所属用户组信息

getgrgid

通过 struct stat 结构体中的 gid_t st_gid 成员变量,获取文件所属用户组信息

头文件:
    #include <sys/types.h>
    #include <grp.h>
原型:
    struct group *getgrgid(gid_t gid);
参数:
    gid_t gid:文件所属用户组的id;
返回值:
    成功,返回存储用户组信息的结构体指针;struct group * ;
    struct group {
        char   *gr_name;       /* group name */
        char   *gr_passwd;     /* group password */
        gid_t   gr_gid;        /* group ID */
        char  **gr_mem;        /* group members */
    };
    失败,返回NULL,更新errno;
例程:
    //提取文件所属用户组的名字
    char* getGrpName(char* grpName, gid_t gid)
    {
        struct group* grp = NULL;
        grp = getgrgid(gid);  
        if(NULL == grp)
        {   
            perror("getgrgid");
            return NULL;
        }   
        strcpy(grpName, grp->gr_name);
        return grpName;
    }

应用例程2

读取一个文件的信息,用main函数外部传参的方式。要求输出结果类似如下:-rw-rw-r-- 1 linux root 236 Mar 29 22:02 1_getfileno.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <pwd.h>
#include <time.h>
#include <grp.h>
//提取文件的权限 方法1
#if 0
void getPermission(mode_t mode)
{/*{{{*/
    //获取当前用户的权限
    if(mode & 0400)
        putchar('r');
    else
        putchar('-');
    if(mode & 0200)
        putchar('w');
    else
        putchar('-');
    if(mode & 0100)
        putchar('x');
    else
        putchar('-');
    /*-----------------*/
    //获取组用户的权限
    if(mode & 0040)
        putchar('r');
    else
        putchar('-');
    if(mode & 0020)
        putchar('w');
    else
        putchar('-');
    if(mode & 0010)
        putchar('x');
    else
        putchar('-');
    /*-----------------*/
    //获取其他用户的权限
    if(mode & 0004)
        putchar('r');
    else
        putchar('-');
    if(mode & 0002)
        putchar('w');
    else
        putchar('-');
    if(mode & 0001)
        putchar('x');
    else
        putchar('-');
    putchar(10);
}/*}}}*/
#endif
//提取文件的权限 方法2
void getPermission(mode_t mode)
{
    int i = 0;
    for(i=8; i>=0; i--)
    {
        if((mode & (1<<i)) == 0)
        {
            putchar('-');
            continue;
        }
        switch(i%3)
        {
        case 2:
            putchar('r');
            break;
        case 1:
            putchar('w');
            break;
        case 0:
            putchar('x');
            break;
        }
    }
}
#if 0
//提取文件类型 方法1
void getType(mode_t m)
{/*{{{*/
    if(S_ISREG(m))
        putchar('-');
    else if(S_ISDIR(m))
        putchar('d');
    else if(S_ISCHR(m))
        putchar('c');
    else if(S_ISBLK(m))
        putchar('b');
    else if(S_ISFIFO(m))
        putchar('p');
    else if(S_ISLNK(m))
        putchar('l');
    else if(S_ISSOCK(m))
        putchar('s');
}/*}}}*/
#endif
//提取文件类型 方法2
void getType(mode_t m)
{
    switch (m & S_IFMT) {
    case S_IFBLK:  printf("b");     break;
    case S_IFCHR:  printf("c");     break;
    case S_IFDIR:  printf("d");     break;
    case S_IFIFO:  printf("p");     break;
    case S_IFLNK:  printf("l");     break;
    case S_IFREG:  printf("-");     break;
    case S_IFSOCK: printf("s");     break;
    default:       printf("unknown?\n");   break;
    }
}
//提取文件所属用户名
char* getUsrName(char*name, uid_t uid)
{
    struct passwd* pwd = NULL;
    pwd = getpwuid(uid);
    if(NULL == pwd)
    {
        perror("getpwuid");
        return NULL;
    } 
    strcpy(name, pwd->pw_name);
    return name;
}
//提取文件所属组用户的名字
char* getGrpName(char* grpName, gid_t gid)
{
    struct group* grp = NULL;
    grp = getgrgid(gid);
    if(NULL == grp)
    {
        perror("getgrgid");
        return NULL;
    }
    strcpy(grpName, grp->gr_name);
    return grpName;
}
int main(int argc, const char *argv[])
{
    if(argc < 2)
    {
        fprintf(stderr, "请输入文件名\n");
        return -1;
    }
    struct stat buf;
    if(stat(argv[1], &buf) < 0)
    {
        perror("stat");
        return -1;
    }
    //文件的inode号
    //printf("inode: %lu\n", buf.st_ino);
    //文件的类型+权限
    getType(buf.st_mode);
    getPermission(buf.st_mode);
    //printf("mode+types:%o\n", buf.st_mode);
    //文件硬连接数
    printf(" %d", buf.st_nlink);
    //文件所属用户的id,uid
    char name[20] = "";
    getUsrName(name, buf.st_uid);
    printf(" %s", name);
    //文件所属组用户的名字
    char grpName[20] = "";
    getGrpName(grpName, buf.st_gid);
    printf(" %s", grpName);
    //文件的大小
    printf(" %ld", buf.st_size);
    //日期
    char time[120] = "";
    strcpy(time, ctime(&buf.st_ctime));
    time[strlen(time)-1] = 0;     //删除'\n'字符
    printf(" %s", time);
    //打印文件名
    printf(" %s", argv[1]);
    putchar(10);
    putchar(10);
    return 0;
}

结果

opendir

打开一个目录文件,并返回目录流指针

头文件:
    #include <sys/types.h>
    #include <dirent.h>
原型:
    DIR *opendir(const char *name);
参数:
    char *name:目录文件的路径;
返回值:
    成功,返回目录流指针;
    失败,返回NULL,更新errno;
例程:
    DIR* dp = opendir("/home/linux/");
    if(NULL == dp)
    {
        perror("opendir");
        return -1;
    }

closedir

关闭目录

头文件:
    #include <sys/types.h>
    #include <dirent.h>
原型:
    int closedir(DIR *dirp);
返回值:
    成功,返回0;
    失败,返回-1,更新errno;
例程:
    closedir(dp);

readdir

通过目录流指针读取目录内容

头文件:
    #include <dirent.h>
原型:
    struct dirent *readdir(DIR *dirp);
参数:
    DIR *dirp:目录流指针;
返回值:
    成功,返回存储目录信息的结构体;
    struct dirent {
        ino_t d_ino;       /* inode number */
        off_t d_off;       /* not an offset; see NOTES */
        unsigned short d_reclen;    /* length of this record */
        unsigned char  d_type;      /* type of file; not supported by all filesystem types */
        char d_name[256]; /* filename */
    };
    失败,返回NULL;
例程:
    struct dirent *readptr = NULL;
    while(1)
    {
        //读取目录,读取到的结果存在readptr中
        readptr = readdir(dp);
        if(NULL == readptr)
        {
            printf("目录读取完毕\n");
            break;
        }
        if(readptr->d_name[0] != '.')
        {
            printf("%s\n", readptr->d_name); //打印读取到的文件名
        }
    }

应用例程3

实现打开目录,显示该目录下所有文件的属性,权限...... 类似ls -l

operateDir.c

#include "getFileStat.h"
#include <dirent.h>
int main(int argc, const char *argv[])
{
    DIR *dp = opendir(argv[1]);
    if(NULL == dp)
    {
        perror("opendir");
        return -1;
    }
    struct dirent *readptr = NULL;
    while(1)
    {
        readptr = readdir(dp);
        if(NULL == readptr)
        {
            printf("当前目录下文件信息打印完毕\n");
            break;
        }
        struct stat buf;
        //获取当前文件路径
        char path[100] = "";
        sprintf(path,"%s/%s",argv[1],readptr->d_name);
        stat(path,&buf);
        get_file_stat(buf,readptr->d_name);
    }
    closedir(dp);
    return 0;
}

getFileStat.c

#include "getFileStat.h"
void get_filemode_lspbcd(mode_t mode)
{
    mode_t m = mode & S_IFMT;
    switch(m)
    {
        case S_IFSOCK:
            putchar('s');
            break;
        case S_IFLNK:
            putchar('l');
            break;
        case S_IFREG:
            putchar('-');
            break;
        case S_IFBLK:
            putchar('b');
            break;
        case S_IFDIR:
            putchar('d');
            break;
        case S_IFCHR:
            putchar('c');
            break;
        case S_IFIFO:
            putchar('p');
    }
}
void get_filemode(mode_t mode)
{
    int i;
    mode_t m;
    for(i=8;i>=0;i--)
    {
        m = mode & 1<<i;
        if(m == 0)
        {
            putchar('-');
            continue;
        }
        switch(i%3)
        {
            case 0:
                putchar('x');
                break;
            case 1:
                putchar('w');
                break;
            case 2:
                putchar('r');
                break;
        }
    }
}
void get_link(nlink_t nlink_t)
{
    printf("%-4ld",(long)nlink_t);
}
void get_uid(uid_t uid)
{
    struct passwd *pwd = NULL;
    if((pwd = getpwuid(uid))!=NULL)
    {
        printf("%s",pwd->pw_name);
    }
}
void get_gid(gid_t gid)
{
    struct group *grp = NULL;
    if((grp = getgrgid(gid))!=NULL)
    {
        printf("%s",grp->gr_name);
    }
}
void get_size(off_t size)
{
    printf("%-10ld",size);
}
void get_time(time_t time)
{
    char t[50] = "";
    sprintf(t,"%s",(char *)ctime(&time));
    t[strlen(t)-1] = '\0';
    printf("%s",t);
}
void get_file_stat(struct stat buf,const char *file)
{
    get_filemode_lspbcd(buf.st_mode);
    get_filemode(buf.st_mode);
    putchar(' ');
    get_link(buf.st_nlink);
    putchar(' ');
    get_uid(buf.st_uid);
    putchar(' ');
    get_gid(buf.st_gid);
    putchar(' ');
    get_size(buf.st_size);
    putchar(' ');
    get_time(buf.st_ctime);
    putchar(' ');
    printf("%s",file);
    putchar(10);
}

getFileStat.h

#ifndef __GETFILESTAT_H__
#define __GETFILESTAT_H__

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <string.h>

void get_filemode_lspbcd(mode_t mode);
void get_filemode(mode_t mode);
void get_link(nlink_t nlink_t);
void get_uid(uid_t uid);
void get_gid(gid_t gid);
void get_size(off_t size);
void get_time(time_t time);
void get_file_stat(struct stat buf,const char *file);

#endif

makefile

a.out:operateDir.o getFileStat.o
    gcc operateDir.o getFileStat.o -o a.out
operateDir.o:operateDir.c
    gcc -c operateDir.c -o operateDir.o
getFileStat.o:getFileStat.c
    gcc -c getFileStat.c -o getFileStat.o

.PHONY:clean
clean:
    rm *.o a.out

结果

Last modification:2021 年 04 月 10 日 11 : 37 : 25