文档配套视频讲解链接地址
- 腾讯课堂视频链接地址 : 物联网-嵌入式Linux应用开发课程
第03章 Linux的文件属性与目录
3.1 获取文件属性
1. stat 函数
- 函数原型
int stat(const char *pathname, struct stat *statbuf);
struct stat {
dev_t st_dev; /* ID of device containing file */ 文件的设备号 , 这个和驱动有关系的参数
ino_t st_ino; /* Inode number */ 文件的唯一ID号, 类似身份证号
mode_t st_mode; /* File type and mode */ 文件的权限 可读可写可执行, 用户 组 其他
nlink_t st_nlink; /* Number of hard links */ 硬链接个数
uid_t st_uid; /* User ID of owner */ 用户id号
gid_t st_gid; /* Group ID of owner */ 组id号
dev_t st_rdev; /* Device ID (if special file) * / 特殊文件的设备号
off_t st_size; /* Total size, in bytes */ 文件大小
blksize_t st_blksize; /* Block size for filesystem I/O */ 在文件系统中, 一个块多少个字节
blkcnt_t st_blocks; /* Number of 512B blocks allocated */ 这个文件占用多少个块
/* Since Linux 2.6, the kernel supports nanosecond
precision for the following timestamp fields.
For the details before Linux 2.6, see NOTES. */
struct timespec st_atim; /* Time of last access */ 最后访问时间
struct timespec st_mtim; /* Time of last modification */ 最后修改时间
struct timespec st_ctim; /* Time of last status change */ 最后状态改变时间
#define st_atime st_atim.tv_sec /* Backward compatibility */ 最后访问的秒数, 用时需要转换成标准时间
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};
- 函数功能
- 获取文件的属性信息
- 函数参数
- pathname: 文件名
- statbuf : 保存文件属性信息的结构体指针
- 函数返回值
- 成功返回: 0
- On success, zero is returned.
- 失败返回 :
- -1 并设置errno
- On error, -1 is returned, and errno is set appropriately.
2. Inode示意图
-
文件系统的分区表
-
文件名类似人的姓名
-
Inode 号类似人的身份证号
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ADk4WN0d-1670758252682)(https://gitee.com/embmaker/cloudimage/raw/master/img/20221014135738.png)]
3. fstat 函数
- 函数原型
int fstat(int fd, struct stat *statbuf);
- 函数功能
- 获取已经打开文件的属性信息
- 函数参数
- fd: 已经打开的文件
- statbuf : 保存文件属性信息的结构体指针
- 函数返回值
- 成功返回: 0
- On success, zero is returned.
- 失败返回 :
- -1 并设置errno
- On error, -1 is returned, and errno is set appropriately.
4. getpwuid 函数
- 函数原型
struct passwd *getpwuid(uid_t uid);
// 解释:
The getpwuid() function returns a pointer to a structure containing the broken-out fields of the
record in the password database that matches the user ID uid.
The passwd structure is defined in <pwd.h> as follows:
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 */
};
- 函数功能
- 根据文件的uid来获取用户名
- 函数参数
- uid: 文件的所有者的id号
- 函数返回值
- 成功返回: 结构体的首地址
- 失败返回 :
- NULL 并设置errno
5. getgrgid 函数
- 函数原型
struct group *getgrgid(gid_t gid);
struct group {
char *gr_name; /* group name */ 组的名称
char *gr_passwd; /* group password */
gid_t gr_gid; /* group ID */
char **gr_mem; /* NULL-terminated array of pointers
to names of group members */
};
- 函数功能
- 根据文件的gid来获取组的用户名
- 函数参数
- gid: 文件的所有组的id号
- 函数返回值
- 成功返回: 结构体的首地址
- 失败返回 :
- NULL 并设置errno
4. 实例28 实现stat命令的功能
-
使用stat函数来实现stat命令的功能
-
源文件
05-linuxio/28-stat.c
- 源代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> /* Definition of AT_* constants */
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
int get_timezone(void)
{
// 获取系统时间的秒数 1970 01 01 00:00:00 到此时的一个秒数
time_t t1 = time(NULL); // 这个秒数, 会有时区的偏移 , 基于当前时区的一个秒数
// printf("t1=%ld\n",t1); // t1 是东8区的秒数
// 秒数转时间结构体
struct tm *tp = gmtime(&t1); // 这个函数 输出的时间是基准时间, 时区为0的基准时间
time_t t2 = mktime(tp); // 把时间结构体 struct tm 转成 time_t 的秒数
// printf("t2=%ld\n",t2); // t2 是0时区的秒数
// printf("t1-t2=%ld\n",t1-t2); // 本地时间 - 基准时间
// printf("t1-t2=%ld\n",(t1-t2)/36); // (本地时间 - 基准时间) 换算为小时
return (t1-t2)/36;
}
int main(int argc, char const *argv[])
{
struct stat st;
if (argc != 2)
{
fprintf(stderr, "程序错误:运行程序时请带入参数(./28-stat filename)\n");
exit(-1);
}
int ret = stat(argv[1], &st);
if (ret < 0)
{
perror("stat");
exit(-1);
}
printf("文件: %s\n", argv[1]); // 输出文件名
printf("大小: %ld\t\t", st.st_size); // 输出文件大小 \t 加上一个tab按键 , 等于4个空格
printf("块: %ld\t\t", st.st_blocks); // 输出文件占用的块
printf("IO块: %ld\t", st.st_blksize); // 文件系统的块大小
switch (st.st_mode & S_IFMT)
{
case S_IFBLK:
printf("普通文件\n");
break;
case S_IFCHR:
printf("字符设备\n");
break;
case S_IFDIR:
printf("目录\n");
break;
case S_IFIFO:
printf("管道文件\n");
break;
case S_IFLNK:
printf("符号连接\n");
break;
case S_IFREG:
printf("普通文件\n");
break;
case S_IFSOCK:
printf("套接字\n");
break;
default:
printf("unknown?\n");
break;
}
printf("设备: %lxh/%ldd\t", st.st_dev, st.st_dev); // 输出文件大小
printf("Inode: %ld\t", st.st_ino); // 输出文件的Inode号
printf("硬链接: %ld\n", st.st_nlink); // 输出文件的硬链接
// 保留st_mode的低9位 , 1个8进制的数占用3位
printf("权限: (%#o/", st.st_mode & 0777); // 输出文件的8进制的权限
/**********文件类型*********************************************************/
switch (st.st_mode & 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;
}
/*************用户权限************************************/
// 获取用户的可读权限
if (st.st_mode & S_IRUSR)
printf("r");
else
printf("-");
// 获取用户的可写权限
if (st.st_mode & S_IWUSR)
printf("w");
else
printf("-");
// 获取用户的可执行权限
if (st.st_mode & S_IXUSR)
printf("x");
else
printf("-");
/*****************组的权限*******************************/
// 获取组的可读权限
if (st.st_mode & S_IRGRP)
printf("r");
else
printf("-");
// 获取组的可写权限
if (st.st_mode & S_IWGRP)
printf("w");
else
printf("-");
// 获取组的可执行权限
if (st.st_mode & S_IXGRP)
printf("x");
else
printf("-");
/*****************其他用户的权限*******************************/
// 获取其它的可读权限
if (st.st_mode & S_IROTH)
printf("r");
else
printf("-");
// 获取其它的可写权限
if (st.st_mode & S_IWOTH)
printf("w");
else
printf("-");
// 获取其它的可执行权限
if (st.st_mode & S_IXOTH)
printf("x");
else
printf("-");
printf(")\t");
/*****************文件所有者*******************************/
struct passwd * pw = getpwuid(st.st_uid) ; // 根据uid获取用户名
printf("Uid: (%d/%s)\t", st.st_uid, pw->pw_name);
struct group *grp = getgrgid(st.st_gid) ; // 根据gid获取 组的名称
printf("Gid: (%d/%s)\n", st.st_gid, grp->gr_name);
struct tm *tmp = localtime(&st.st_atime); // st_atime 就是秒数 最后访问时间
printf("最近访问: %04d-%02d-%02d %02d:%02d:%02d.%09ld %+05d\n", tmp->tm_year + 1900,
tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min,
tmp->tm_sec, st.st_atim.tv_nsec, get_timezone());
tmp = localtime(&st.st_mtime); // st_atime 就是秒数 最后更改时间
printf("最近访问: %04d-%02d-%02d %02d:%02d:%02d.%09ld %+05d\n", tmp->tm_year + 1900,
tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min,
tmp->tm_sec, st.st_mtim.tv_nsec, get_timezone());
tmp = localtime(&st.st_ctime); // st_atime 就是秒数 最后状态改动时间
printf("最近访问: %04d-%02d-%02d %02d:%02d:%02d.%09ld %+05d\n", tmp->tm_year + 1900,
tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min,
tmp->tm_sec, st.st_ctim.tv_nsec, get_timezone());
return 0;
}
- 运行结果
linux@ubuntu:~/work/emb2207/05-linuxio$ ./28-stat 01-fopen.c
文件: 01-fopen.c
大小: 1110 块: 8 IO块: 4096 普通文件
设备: 801h/2049d Inode: 3017194 硬链接: 1
权限: (0664/-rw-rw-r--) Uid: (1000/linux) Gid: (1000/linux)
最近访问: 2022-10-14 08:00:08.026939918 +0800
最近访问: 2022-10-14 08:00:08.309500914 +0800
最近访问: 2022-10-14 08:00:08.309500914 +0800
linux@ubuntu:~/work/emb2207/05-linuxio$ stat 01-fopen.c
文件:01-fopen.c
大小:1110 块:8 IO 块:4096 普通文件
设备:801h/2049d Inode:3017194 硬链接:1
权限:(0664/-rw-rw-r--) Uid:( 1000/ linux) Gid:( 1000/ linux)
最近访问:2022-10-13 10:00:40.026939918 +0800
最近更改:2022-10-11 15:03:12.309500914 +0800
最近改动:2022-10-11 15:03:12.309500914 +0800
创建时间:-
linux@ubuntu:~/work/emb2207/05-linuxio$
- 这个程序有bug, 问题是
linux@ubuntu:~/work/emb2207/05-linuxio$ ./28-stat 01-fopen.c
文件: 01-fopen.c
大小: 1110 块: 8 IO块: 4096 普通文件
设备: 801h/2049d Inode: 3017194 硬链接: 1
权限: (0664/-rw-rw-r--) Uid: (1000/linux) Gid: (1000/linux)
最近访问: 2022-10-14 08:00:08.026939918 +0800
最近访问: 2022-10-14 08:00:08.309500914 +0800
最近访问: 2022-10-14 08:00:08.309500914 +0800
// 输出的时间都是一样的 , 这个问题解决请参考如下代码
- 问题解决核心代码
int timezone = get_timezone(); // 把时区单独提取出来进行保存
struct tm *tmp = localtime(&st.st_atime); // st_atime 就是秒数 最后访问时间
printf("最近访问: %04d-%02d-%02d %02d:%02d:%02d.%09ld %+05d\n", tmp->tm_year + 1900,
tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min,
tmp->tm_sec, st.st_atim.tv_nsec, timezone);
tmp = localtime(&st.st_mtime); // st_mtime 就是秒数 最后更改时间
printf("最近更改: %04d-%02d-%02d %02d:%02d:%02d.%09ld %+05d\n", tmp->tm_year + 1900,
tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min,
tmp->tm_sec, st.st_mtim.tv_nsec, timezone);
tmp = localtime(&st.st_ctime); // st_ctime 就是秒数 最后状态改动时间
printf("最近改动: %04d-%02d-%02d %02d:%02d:%02d.%09ld %+05d\n", tmp->tm_year + 1900,
tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min,
tmp->tm_sec, st.st_ctim.tv_nsec, timezone);
3.2 目录操作
1. opendir 打开目录
- 函数原型
DIR *opendir(const char *name);
/* This is the data type of directory stream objects.
The actual structure is opaque to users. */
typedef struct __dirstream DIR;
- 函数功能
- 打开指定的目录
- 函数参数
- name: 要打开目录的名称
- 函数返回值
- 成功返回: 结构体的首地址
- 失败返回 :
- NULL 并设置errno
- On error, NULL is returned, and errno is set appropriately.
2. closedir 关闭目录
- 函数原型
int closedir(DIR *dirp);
- 函数功能
- 关闭已经打开的目录
- 函数参数
- dirp: 要关闭的目录指针
- 函数返回值
- 成功返回: 0
- 失败返回 :
- -1 并设置errno
- On error, -1 is returned, and errno is set appropriately.
3. readdir 读目录
- 函数原型
struct dirent *readdir(DIR *dirp);
struct dirent {
ino_t d_ino; /* Inode number */
off_t d_off; /* Not an offset; see below */
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]; /* Null-terminated filename */ 目录中的内容 , 目录内有子目录或文件名
};
- 函数功能
- 读已经打开的目录
- 函数参数
- dirp: 要读目录的指针
- 函数返回值
- 成功返回: 结构体的首地址
- NULL 表示目录读完 , 不设置errno
- If the end of the directory stream is reached, NULL is returned and errno is not changed
- 失败返回 :
- NULL 并设置errno
- If an error occurs, NULL is returned and errno is set appropriately.
4. rmdir 删除目录
- 函数原型
int rmdir(const char *pathname);
- 函数功能
- 删除指定的目录
- 函数参数
- pathname: 要删除的目录
- 函数返回值
- 成功返回: 0
- On success, zero is returned.
- 失败返回 :
- -1并设置errno
- On error, -1 is returned, and errno is set appropriately.
5. mkdir 创建目录
- 函数原型
int mkdir(const char *pathname, mode_t mode);
- 函数功能
- 用给定的权限创建一个目录
- 函数参数
- pathname: 要创建的目录
- mode : 创建目录的权限, 和open函数的权限一样
- 函数返回值
- 成功返回: 0
- On success, zero is returned.
- 失败返回 :
- -1并设置errno
- On error, -1 is returned, and errno is set appropriately.
6. chdir 切换目录
- 函数原型
int chdir(const char *path);
- 函数功能
- 切换目录, 等同于命令的cd
- 函数参数
- path: 要切换的目录
- 函数返回值
- 成功返回: 0
- On success, zero is returned.
- 失败返回 :
- -1并设置errno
- On error, -1 is returned, and errno is set appropriately.
7. 实例29 读取指定目录的内容
-
使用opendir, readdir , closedir 读取目录中的内容
-
源文件
05-linuxio/29-opendir.c
- 源代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
int main(int argc, char const *argv[])
{
struct dirent *dt;
if(argc != 2)
{
fprintf(stderr,"错误:运行程序时请带入参数(./29-opendir path)\n");
exit(-1);
}
DIR * dirp = opendir(argv[1]);
if(dirp == NULL)
{
perror("opendir");
exit(-1);
}
while( (dt=readdir(dirp)) != NULL )
{
if(strncmp(dt->d_name,".",1) == 0 ) continue;
printf("%s ",dt->d_name);
}
printf("\n");
closedir(dirp);
return 0;
}
- 运行结果
linux@ubuntu:~/work/emb2207/05-linuxio$ ./29-opendir /home/linux/
Downloads Templates Videos Desktop Pictures snap Documents work Public Music id_rsa.pub
linux@ubuntu:~/work/emb2207/05-linuxio$ ls /home/linux/
Desktop Documents Downloads id_rsa.pub Music Pictures Public snap Templates Videos work
linux@ubuntu:~/work/emb2207/05-linuxio$
8. 实例 30 综合练习myls
-
编程实现ls 和 ls -l 命令的功能
-
提示 : 封装2个函数 , process_ls 和 process_ls_l
-
源文件
05-linuxio/30-myls.c
- 源代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
int process_ls(const char *arg)
{
// printf("argv=%s\n",arg);
// printf("process_ls\n");
struct dirent *dt;
DIR *dirp = opendir(arg);
if (dirp == NULL)
{
perror("opendir");
exit(-1);
}
while ((dt = readdir(dirp)) != NULL)
{
if (strncmp(dt->d_name, ".", 1) == 0)
continue;
printf("%s ", dt->d_name);
}
printf("\n");
closedir(dirp);
return 0;
}
int process_ls_l(const char *arg)
{
// printf("argv=%s\n", arg);
// printf("process_ls_l\n");
struct dirent *dt;
struct stat st;
char filename[300] = {0};
struct tm *tmp;
DIR *dirp = opendir(arg);
if (dirp == NULL)
{
perror("opendir");
exit(-1);
}
while ((dt = readdir(dirp)) != NULL)
{
if (strncmp(dt->d_name, ".", 1) == 0)
continue;
if (arg[strlen(arg) - 1] == '/')
{
sprintf(filename, "%s%s", arg, dt->d_name);
}
else
{
sprintf(filename, "%s/%s", arg, dt->d_name);
}
//printf("%s\n", filename);
int ret = stat(filename, &st);
if (ret < 0)
{
perror("stat");
exit(-1);
}
/**********文件类型*********************************************************/
switch (st.st_mode & 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;
}
/*************用户权限************************************/
// 获取用户的可读权限
if (st.st_mode & S_IRUSR)
printf("r");
else
printf("-");
// 获取用户的可写权限
if (st.st_mode & S_IWUSR)
printf("w");
else
printf("-");
// 获取用户的可执行权限
if (st.st_mode & S_IXUSR)
printf("x");
else
printf("-");
/*****************组的权限*******************************/
// 获取组的可读权限
if (st.st_mode & S_IRGRP)
printf("r");
else
printf("-");
// 获取组的可写权限
if (st.st_mode & S_IWGRP)
printf("w");
else
printf("-");
// 获取组的可执行权限
if (st.st_mode & S_IXGRP)
printf("x");
else
printf("-");
/*****************其他用户的权限*******************************/
// 获取其它的可读权限
if (st.st_mode & S_IROTH)
printf("r");
else
printf("-");
// 获取其它的可写权限
if (st.st_mode & S_IWOTH)
printf("w");
else
printf("-");
// 获取其它的可执行权限
if (st.st_mode & S_IXOTH)
printf("x");
else
printf("-");
/*****************硬链接的数量*****************************/
printf(" %ld", st.st_nlink);
/*****************文件所有者*******************************/
struct passwd *pw = getpwuid(st.st_uid); // 根据uid获取用户名
printf(" %s", pw->pw_name);
struct group *grp = getgrgid(st.st_gid); // 根据gid获取 组的名称
printf(" %s ", grp->gr_name);
/*******************文件的大小*****************************/
printf("%4ld ", st.st_size);
/*******************文件的修改时间**************************/
tmp = localtime(&st.st_mtime); // st_mtime 就是秒数 最后更改时间
printf("%02d月%02d %02d:%02d ", tmp->tm_mon + 1, tmp->tm_mday,
tmp->tm_hour, tmp->tm_min );
printf("%s\n",dt->d_name);
}
closedir(dirp);
return 0;
}
int main(int argc, char const *argv[])
{
struct dirent *dt;
if (argc == 2) // ls /
{
process_ls(argv[1]); // path
}
else if (argc == 3) // ls -l /
{
process_ls_l(argv[2]); // path
}
else
{
fprintf(stderr, "错误:运行程序时请带入参数(./30-myls path 或者 ./myls -l path )\n");
exit(-1);
}
return 0;
}
- 运行结果
linux@ubuntu:~/work/emb2207/05-linuxio$ ls /home/linux/
Desktop Documents Downloads id_rsa.pub Music Pictures Public snap Templates Videos work
linux@ubuntu:~/work/emb2207/05-linuxio$ ls -l /home/linux/
总用量 44
drwxr-xr-x 2 linux linux 4096 9月 6 08:48 Desktop
drwxr-xr-x 2 linux linux 4096 8月 23 16:17 Documents
drwxr-xr-x 2 linux linux 4096 8月 16 11:03 Downloads
-rw------- 1 linux linux 569 9月 6 08:57 id_rsa.pub
drwxr-xr-x 2 linux linux 4096 8月 16 11:03 Music
drwxr-xr-x 2 linux linux 4096 8月 16 11:03 Pictures
drwxr-xr-x 2 linux linux 4096 8月 16 11:03 Public
drwx------ 4 linux linux 4096 8月 17 10:19 snap
drwxr-xr-x 2 linux linux 4096 8月 16 11:03 Templates
drwxr-xr-x 2 linux linux 4096 8月 16 11:03 Videos
drwxrwxr-x 3 linux linux 4096 9月 20 09:23 work
linux@ubuntu:~/work/emb2207/05-linuxio$
// 功能如下:
linux@ubuntu:~/work/emb2207/05-linuxio$ ./30-myls -l /home/linux
drwxr-xr-x 2 linux linux 4096 08月16 11:03 Downloads
drwxr-xr-x 2 linux linux 4096 08月16 11:03 Templates
drwxr-xr-x 2 linux linux 4096 08月16 11:03 Videos
drwxr-xr-x 2 linux linux 4096 09月06 08:48 Desktop
drwxr-xr-x 2 linux linux 4096 08月16 11:03 Pictures
drwx------ 4 linux linux 4096 08月17 10:19 snap
drwxr-xr-x 2 linux linux 4096 08月23 16:17 Documents
drwxrwxr-x 3 linux linux 4096 09月20 09:23 work
drwxr-xr-x 2 linux linux 4096 08月16 11:03 Public
drwxr-xr-x 2 linux linux 4096 08月16 11:03 Music
-rw------- 1 linux linux 569 09月06 08:57 id_rsa.pub
linux@ubuntu:~/work/emb2207/05-linuxio$ ./30-myls -l /home/linux/
drwxr-xr-x 2 linux linux 4096 08月16 11:03 Downloads
drwxr-xr-x 2 linux linux 4096 08月16 11:03 Templates
drwxr-xr-x 2 linux linux 4096 08月16 11:03 Videos
drwxr-xr-x 2 linux linux 4096 09月06 08:48 Desktop
drwxr-xr-x 2 linux linux 4096 08月16 11:03 Pictures
drwx------ 4 linux linux 4096 08月17 10:19 snap
drwxr-xr-x 2 linux linux 4096 08月23 16:17 Documents
drwxrwxr-x 3 linux linux 4096 09月20 09:23 work
drwxr-xr-x 2 linux linux 4096 08月16 11:03 Public
drwxr-xr-x 2 linux linux 4096 08月16 11:03 Music
-rw------- 1 linux linux 569 09月06 08:57 id_rsa.pub
linux@ubuntu:~/work/emb2207/05-linuxio$ ./30-myls /home/linux/
Downloads Templates Videos Desktop Pictures snap Documents work Public Music id_rsa.pub
linux@ubuntu:~/work/emb2207/05-linuxio$ ./30-myls /home/linux
Downloads Templates Videos Desktop Pictures snap Documents work Public Music id_rsa.pub
linux@ubuntu:~/work/emb2207/05-linuxio$
3.3 知识点补充
1. umask 函数
- 函数原型
mode_t umask(mode_t mask);
-
函数功能
- 权限屏蔽
-
函数参数
- mask: 给的屏蔽位
- 例如 : 0111 的屏蔽位, 将来的文件权限
umask(0111) open("1.txt",O_RDWR|O_CREAT|O_APPEND,0664) ; //设置新创建文件的权限位0664 // 最终的文件权限为: // 0111 按位取反 与上 0664 , 才是文件最终的权限 // = ~0111 & 0664 // = 0666 & 0664 // = 0664
-
函数返回值
- 成功返回: 之前屏蔽位的值
- This system call always succeeds and the previous value of the mask is returned.
2. 实例31 文件权限屏蔽位
- 源文件
05-linuxio/31-umask.c
- 源代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char const *argv[])
{
mode_t mask = umask(0777);
printf("mask = %#o\n", mask);
// 最终的文件权限位:
// = ~0777 & 0777
// = 0000 & 0777
// = 0000
int fd = open("1.txt", O_RDWR | O_CREAT | O_APPEND, 0777); //设置新创建文件的权限位0777
if (fd < 0)
{
perror("1:open");
exit(-1);
}
printf("fd=%d\n", fd);
umask(0);
// 最终的文件权限位:
// = ~0000 & 0777
// = 0777 & 0777
// = 0777
int fd2 = open("2.txt", O_RDWR | O_CREAT | O_APPEND, 0777); //设置新创建文件的权限位0777
if (fd2 < 0)
{
perror("2:open");
exit(-1);
}
printf("fd2=%d\n", fd2);
umask(02); // 系统默认的权限
// 最终的文件权限位:
// = ~0000 & 0777
// = 0777 & 0777
// = 0777
int fd3 = open("3.txt", O_RDWR | O_CREAT | O_APPEND, 0777); //设置新创建文件的权限位0777
if (fd3 < 0)
{
perror("2:open");
exit(-1);
}
printf("fd3=%d\n", fd3);
return 0;
}
- 运行结果
linux@ubuntu:~/work/emb2207/05-linuxio$ ./31-umask
mask = 02
fd=3
fd2=4
fd3=5
linux@ubuntu:~/work/emb2207/05-linuxio$ ls -l 1.txt 2.txt 3.txt
---------- 1 linux linux 0 10月 15 16:17 1.txt // 0000
-rwxrwxrwx 1 linux linux 0 10月 15 16:17 2.txt // 0777
-rwxrwxr-x 1 linux linux 0 10月 15 16:17 3.txt // 0775
3. access 函数
- 函数原型
int access(const char *pathname, int mode);
- 函数功能
- 检查一个文件的权限(可读, 可写,可执行, 是否存在)
- 函数参数
- pathname: 要检查的文件名
- mode :
- F_OK : 测试文件是否存在
- R_OK : 可读
- W_OK : 可写
- X_OK. : 可执行
- 返回值:
- 成功返回: 0
- 失败返回: -1 并设置errno
- On success (all requested permissions granted, or mode is F_OK and the file exists), zero is returned. On
error (at least one bit in mode asked for a permission that is denied, or mode is F_OK and the file does not
exist, or some other error occurred), -1 is returned, and errno is set appropriately.
4. 实例32 access
-
检查一个文件是否存在, 如果存在就删除, 不存在创建
-
源文件
05-linuxio/32-access.c
- 源代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
if (argc != 2)
{
fprintf(stderr, "错误:运行程序时请带入参数(./32-access filename)\n");
exit(-1);
}
// 返回值为0 , 表示文件存在
// 返回值为-1 ,表示文件不存在
if (access(argv[1],F_OK) == 0 ) // 文件存在
{
printf("%s:文件存在\n",argv[1]);
remove(argv[1]); // 删除文件
}
int fd = open(argv[1], O_RDWR | O_CREAT | O_APPEND, 0664); //设置新创建文件的权限位0777
if (fd < 0)
{
perror("1:open");
exit(-1);
}
printf("fd=%d\n", fd);
return 0;
}
- 运行结果
linux@ubuntu:~/work/emb2207/05-linuxio$ echo "goodbye" >>1.txt
linux@ubuntu:~/work/emb2207/05-linuxio$ ls -l 1.txt
-rw-rw-r-- 1 linux linux 8 10月 15 16:55 1.txt
linux@ubuntu:~/work/emb2207/05-linuxio$ ./32-access 1.txt
1.txt:文件存在
fd=3
linux@ubuntu:~/work/emb2207/05-linuxio$ cat 1.txt
linux@ubuntu:~/work/emb2207/05-linuxio$