Yuchuan_linux_C 编程之八 文件操作相关函数

一、整体大纲

st_mode整体介绍:

st_mode详细介绍:

二、 Linux文件操作相关函数

1. stat

  • 作用:获得文件信息,也可以获取文件大小。
  • 头文件
1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include <unistd.h>
  • 函数原型
1 int stat(const char *path, struct stat *buf);
2 int fstat(int fd, struct stat *buf);
3 int lstat(const char *path, struct stat *buf);
  • 参数说明:

           path文件名
           buf传出参数,定义结构体struct stat sb; &sb

  • 返回值

          失败:返回-1,设置errno
          成功:返回0

注意: stat碰到链接,会追溯到源文件,穿透!!!lstat并不会穿透。

stat结构体:
 1 struct stat {
 2                dev_t     st_dev;     /* ID of device containing file */
 3                ino_t     st_ino;     /* inode number */
 4                mode_t    st_mode;    /* protection */
 5                nlink_t   st_nlink;   /* number of hard links */
 6                uid_t     st_uid;     /* user ID of owner */
 7                gid_t     st_gid;     /* group ID of owner */
 8                dev_t     st_rdev;    /* device ID (if special file) */
 9                off_t     st_size;    /* total size, in bytes */
10                blksize_t st_blksize; /* blocksize for file system I/O */
11                blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
12 
13                time_t    st_atime;   /* time of last access */
14                time_t    st_mtime;   /* time of last modification */
15                time_t    st_ctime;   /* time of last status change */
16 };
struct stat

linux命令stat执行结果:

1 [root@centos linuxC]# stat stat.c
2   文件:"stat.c"
3   大小:1857            块:8          IO 块:4096   普通文件
4 设备:fd00h/64768d      Inode:17763202    硬链接:1
5 权限:(0644/-rw-r--r--)  Uid:(    0/    root)   Gid:(    0/    root)
6 环境:unconfined_u:object_r:usr_t:s0
7 最近访问:2019-04-27 19:17:15.149083960 +0800
8 最近更改:2019-04-27 19:17:15.149083960 +0800
9 最近改动:2019-04-27 19:17:15.202084912 +0800

注意三个时间的区别

1 time_t    st_atime;   /* time of last access */ 文件被读,比如cat,open读等
2 time_t    st_mtime;   /* time of last modification */  文件内容发生改变
3 time_t    st_ctime;   /* time of last status change */ 文件属性发生变化,比如大小,权限,硬连接数等

上图的解释:

0-2 其他用户权限
3-5 组用户权限
6-8 用户权限
9-11 特殊权限位
12-15 文件类型

示例:

 1 #include <sys/types.h>
 2 #include <sys/stat.h>
 3 #include <time.h>
 4 #include <stdio.h>
 5 #include <stdlib.h>
 6 
 7 int
 8 main(int argc, char *argv[])
 9 {
10     struct stat sb;
11 
12     if (argc != 2) {
13         fprintf(stderr, "Usage: %s <pathname>
", argv[0]);
14         exit(EXIT_FAILURE);
15     }
16 
17     if (stat(argv[1], &sb) == -1) {
18         perror("stat");
19         exit(EXIT_FAILURE);
20     }
21 
22     printf("File type:                ");
23 
24     switch (sb.st_mode & S_IFMT) {
25     case S_IFBLK:  printf("block device
");            break;
26     case S_IFCHR:  printf("character device
");        break;
27     case S_IFDIR:  printf("directory
");               break;
28     case S_IFIFO:  printf("FIFO/pipe
");               break;
29     case S_IFLNK:  printf("symlink
");                 break;
30     case S_IFREG:  printf("regular file
");            break;
31     case S_IFSOCK: printf("socket
");                  break;
32     default:       printf("unknown?
");                break;
33     }
34     printf("I-node number:            %ld
", (long) sb.st_ino);
35 
36     printf("Mode:                     %lo (octal)
",
37             (unsigned long) sb.st_mode);
38 
39     printf("Link count:               %ld
", (long) sb.st_nlink);
40     printf("Ownership:                UID=%ld   GID=%ld
",
41             (long) sb.st_uid, (long) sb.st_gid);
42 
43     printf("Preferred I/O block size: %ld bytes
",
44             (long) sb.st_blksize);
45     printf("File size:                %lld bytes
",
46             (long long) sb.st_size);
47     printf("Blocks allocated:         %lld
",
48             (long long) sb.st_blocks);
49 
50     printf("Last status change:       %s", ctime(&sb.st_ctime));
51     printf("Last file access:         %s", ctime(&sb.st_atime));
52     printf("Last file modification:   %s", ctime(&sb.st_mtime));
53 
54     exit(EXIT_SUCCESS);
55 }
56 
57 Linux自带示例(打印文件相关信息)
Linux自带示例(打印文件相关信息)

需求:使用stat实现实现 ls -l  的功能?如下所示

1 [root@centos linuxC]# ll -l xx.log
2 -rw-r--r--. 1 root root 0 4月  27 23:25 xx.log

在实现的过程中需要获取用户名及组名,因此先看两个函数:

1)getpwuid
  • 作用:通过用户的uid获取用户名
  • 头文件
1 #include <sys/types.h>
2 #include <pwd.h>
  • 函数原型
1 struct passwd *getpwuid(uid_t uid);
  • 参数说明:

           uid用户的uid

  • 返回值

          失败:返回NULL
          成功:返回 struct passwd * 结构体指针

 其中:

1 struct passwd {
2     char   *pw_name;       /* username */  用户名
3     char   *pw_passwd;     /* user password */
4     uid_t   pw_uid;        /* user ID */
5     gid_t   pw_gid;        /* group ID */
6     char   *pw_gecos;      /* user information */
7     char   *pw_dir;        /* home directory */
8     char   *pw_shell;      /* shell program */
9 };
struct passwd
2)getgrgid
  • 作用:通过用户的gid获取用户组名
  • 头文件
1 #include <sys/types.h>
2 #include <grp.h>
  • 函数原型
1 struct group *getgrgid(gid_t gid);
  • 参数说明:

           gid用户组的gid

  • 返回值

          失败:返回NULL
          成功:返回 struct group * 结构体指针

其中:

1 struct group {
2     char   *gr_name;       /* group name */
3     char   *gr_passwd;     /* group password */
4     gid_t   gr_gid;        /* group ID */
5     char  **gr_mem;        /* group members */
6 };
struct group
3)localtime
  • 作用:获取本地时间
  • 头文件
1 #include <time.h>
  • 函数原型
1 struct tm *localtime(const time_t *timep);
  • 参数说明:

           timep:一个时间相关的结构体

  • 返回值

          失败:返回NULL
          成功:返回 struct tm * 结构体指针

 其中:

 1 struct tm {
 2     int tm_sec;         /* seconds */
 3     int tm_min;         /* minutes */
 4     int tm_hour;        /* hours */
 5     int tm_mday;        /* day of the month */
 6     int tm_mon;         /* month */
 7     int tm_year;        /* year */
 8     int tm_wday;        /* day of the week */
 9     int tm_yday;        /* day in the year */
10     int tm_isdst;       /* daylight saving time */
11 };
struct tm

传入参数 timep 对应stat函数得到的结构体的秒数(time_t类型)。

 最终实现:

 1 #include<stdio.h>
 2 #include<unistd.h>
 3 #include<sys/types.h>
 4 #include<sys/stat.h>
 5 #include<fcntl.h>
 6 #include<string.h>
 7 #include<time.h>
 8 #include <grp.h>
 9 #include <pwd.h>
10 
11 int main(int argc, char *argv[])
12 {
13     if (argc != 2)
14     {
15         printf("./a.out filename
");
16         return -1;
17     }
18     struct stat sb;
19     stat(argv[1], &sb);
20 
21     char stmode[11] = {0};
22     memset(stmode, '-', sizeof(stmode)-1);
23 
24     //解析文件属性
25     if (S_ISREG(sb.st_mode)) stmode[0] = '-'; //普通文件
26     if (S_ISDIR(sb.st_mode)) stmode[0] = 'd';
27     if (S_ISCHR(sb.st_mode)) stmode[0] = 'c';
28     if (S_ISBLK(sb.st_mode)) stmode[0] = 'b';
29     if (S_ISFIFO(sb.st_mode)) stmode[0] = 'p';
30     if (S_ISLNK(sb.st_mode))  stmode[0] = 'l';
31     if (S_ISSOCK(sb.st_mode)) stmode[0] = 's';
32 
33     //解析权限
34     //user
35     if (sb.st_mode & S_IRUSR) stmode[1] = 'r';
36     if (sb.st_mode & S_IWUSR) stmode[2] = 'w';
37     if (sb.st_mode & S_IXUSR) stmode[3] = 'x';
38     //group
39     if (sb.st_mode & S_IRGRP) stmode[4] = 'r';
40     if (sb.st_mode & S_IWGRP) stmode[5] = 'w';
41     if (sb.st_mode & S_IXGRP) stmode[6] = 'x';
42     //other
43     if (sb.st_mode & S_IROTH) stmode[7] = 'r';
44     if (sb.st_mode & S_IWOTH) stmode[9] = 'w';
45     if (sb.st_mode & S_IXOTH) stmode[10] = 'x';
46 
47     //分析 用户名,组名可以通过函数获得 getpwuid, getgrgid
48     //时间获取
49     struct tm *filetm = localtime(&sb.st_atim.tv_sec);
50     char timebuf[20] = {0};
51     sprintf(timebuf, "%d月    %d %02d:%02d", filetm->tm_mon+1, filetm->tm_mday, filetm->tm_hour, filetm->tm_min);
52 
53     printf("%s %ld %s %s %ld %s %s
", stmode, sb.st_nlink, getpwuid(sb.st_uid)->pw_name,
54            getgrgid(sb.st_gid)->gr_name, sb.st_size, timebuf, argv[1]);
55 
56     return 0;
57 }
58 
59 使用stat实现一个ls -l命令
使用stat实现一个ls -l命令

2. access

  • 作用:测试指定文件是否有某种权限
  • 头文件
1 #include <unistd.h>
  • 函数原型
1 int access(const char *pathname, int mode);
  • 参数说明:

           pathname文件名
           mode:

                   R_OK
                   W_OK
                   X_OK
                   F_OK

  • 返回值

          失败:返回-1,设置errno
          成功:如果有权限或者文件存在,对应返回0

 1 #include<stdio.h>
 2 #include <unistd.h>
 3 
 4 int main(int argc, char *argv[])
 5 {
 6     if (argc != 2)
 7     {
 8         printf("./a.out filename
");
 9         return -1;
10     }
11     if (access(argv[1], R_OK) == 0) printf("%s read ok!
", argv[1]);
12     if (access(argv[1], W_OK) == 0) printf("%s write ok!
", argv[1]);
13     if (access(argv[1], X_OK) == 0) printf("%s exe ok!
", argv[1]);
14     if (access(argv[1], F_OK) == 0) printf("%s file exists!
", argv[1]);
15 
16     return 0;
17 
18 }
19 
20 判断文件读写执行及文件是否存在
判断文件读写执行及文件是否存在

3. chmod

1 #include <sys/stat.h>
2 int chmod(const char *path, mode_t mode);

4. truncate

  • 函数作用:截断文件
  • 头文件
1 #include <unistd.h>
2 #include <sys/types.h>
  • 函数原型
1 int truncate(const char *path, off_t length);
2 int ftruncate(int fd, off_t length);
  • 参数说明:

           path文件名
           length长度,长度如果大于原文件,直接拓展,如果小于原文件,截断为length长度。

  • 返回值

          成功:返回0
          失败:返回-1,设置errno

 示例:

 1 #include<stdio.h>
 2 #include<sys/types.h>
 3 #include<stdio.h>
 4 
 5 int main(int argc, char *argv[])
 6 {
 7     if (argc != 2)
 8     {
 9         printf("./a.out filename
");
10         return -1;
11     }
12     truncate(argv[1], 1024);
13     return 0;
14 }
15 
16 truncate示例
truncate示例

5. link

  • 函数作用:创建硬连接
  • 头文件
1 #include <unistd.h>
  • 函数原型
1 int link(const char *oldpath, const char *newpath);
  • 参数说明:

           oldpath原文件

           newpath硬连接文件

  • 返回值

           成功:返回0
           失败:返回-1,设置errno

 示例:

 1 #include<stdio.h>
 2 #include <unistd.h>
 3 
 4 int main(int argc, char *argv[])
 5 {
 6     if (argc != 2)
 7     {
 8         printf("./a.out filename
");
 9         return -1;
10     }
11 
12     char filename[1024] = {0};
13     sprintf(filename, "%s_hard", argv[1]);
14 
15     link(argv[1], filename);
16 
17     return 0;
18 }
19 
20 创建硬连接示例
创建硬连接示例

6. symlink

  • 函数作用:创建软连接
  • 头文件
1 #include <unistd.h>
  • 函数原型
1 int symlink(const char *oldpath, const char *newpath);
  • 参数解释:

           oldpath原文件
           newpath创建软连接文件

  • 返回值

          成功:返回0
          失败:返回-1,设置errno

 示例:

 1 #include<stdio.h>
 2 #include <unistd.h>
 3 
 4 int main(int argc, char *argv[])
 5 {
 6     if (argc != 2)
 7     {
 8         printf("./a.out filename
");
 9         return -1;
10     }
11 
12     char filename[1024] = {0};
13     sprintf(filename, "%s_soft", argv[1]);
14 
15     symlink(argv[1], filename);
16 
17     return 0;
18 }
19 
20 创建软连接
创建软连接

6. readlink

  • 函数作用:读取文件链接信息
  • 头文件
1 #include <unistd.h>
  • 函数原型
1 ssize_t readlink(const char *path, char *buf, size_t bufsiz);
  • 参数解释:

          path链接名
          buf缓冲区
          bufsiz缓冲区大小

  • 返回值

          成功:返回buf填充的大小
          失败:返回-1,设置errno

 示例:

 1 #include<stdio.h>
 2 #include <unistd.h>
 3 
 4 int main(int argc, char *argv[])
 5 {
 6     if (argc != 2)
 7     {
 8         printf("./a.out filename
");
 9         return -1;
10     }
11 
12     char buf[32] = {0};
13     readlink(argv[1], buf, sizeof(buf));
14     printf("buf is %s
", buf);
15 
16     unlink(argv[1]);
17 
18     return 0;
19 }
20 
21 readlink示例
readlink示例

7. unlink

  • 函数作用:删除软硬链接
  • 头文件
1 #include <unistd.h>
  • 函数原型
1 int unlink(const char *pathname);
  • 函数参数:

          pathname 链接名,文件也可以

  • 返回值

          成功:返回0
          失败:返回-1,设置errno

示例:

 1 #include<stdio.h>
 2 #include <unistd.h>
 3 #include<stdlib.h>
 4 #include<fcntl.h>
 5 #include<string.h>
 6 #include<sys/types.h>
 7 
 8 int main(int argc, char *argv[])
 9 {
10     if (argc != 2)
11     {
12         printf("./a.out filename
");
13         return -1;
14     }
15 
16     int fd = open(argv[1], O_WRONLY|O_CREAT, 0666);
17    //注意只要有进程在使用该文件,则unlink在该文件退出时删除该文件
18     unlink(argv[1]);  
19 
20     int ret = write(fd, "hello", 5);
21     if (ret > 0)
22     {
23         printf("write ok! %d
", ret);
24     }
25     if (ret < 0)
26     {
27         perror("write err");
28     }
29 
30     close(fd);
31 
32     return 0;
33 }
34 
35 unlink示例
unlink示例

8. chown

  • 函数作用:修改文件属主及属组
  • 头文件
1 #include <unistd.h>
  • 函数原型
1 int chown(const char *path, uid_t owner, gid_t group);
  • 函数参数:

          path文件名
          owner用户ID,/etc/passwd
          owner组ID,/etc/group

  • 返回值

          成功:返回0
          失败:返回-1,设置errno

9. rename

    • 函数作用:文件或者目录重命名
    • 头文件
1 #include <stdio.h>
  • 函数原型
1 int rename(const char *oldpath, const char *newpath);
  • 参数说明:

           oldpath文件名
           newpath文件新名

  • 返回值

          成功:返回0
          失败:返回-1,设置errno

示例:

 1 #include<stdio.h>
 2 
 3 int main(int argc, char *argv[])
 4 {
 5     if (argc != 2)
 6     {
 7         printf("./a.out filename
");
 8         return -1;
 9     }
10 
11     char buf[1024] = {0};
12     sprintf(buf, "%s_new", argv[1]);
13     rename(argv[1], buf);
14 
15     return 0;
16 }
17 
18 rename示例
rename示例
原文地址:https://www.cnblogs.com/YuchuanHuaying/p/11146605.html