Linux文件系统实验(C语言实现新建、打开、关闭、读写文件以及查改文件权限)
题目描述:
使用文件系统调用编写一个文件工具 filetools,使其具有以下功能:
- 1.创建新文件
- 2.写文件
- 3.读文件
- 4.修改文件权限
- 5.查看当前文件权限
- 0.退出
- 提示用户输入功能号,并根据用户输入的功能选择相应的功能。
文件按可变记录文件组织,具体记录内容自行设计。
算法设计:
打开/新建文件(open)
调用open可以打开或创建一个文件。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int oflag, ... /* mode_t mode */);
返回若成功为文件描述符,若出错为- 1
参数:
第一个参数**pathname*
是要打开或创建的文件的名字。
第二个参数oflag参数可用来说明此函数的多个选择项。用下列一个或多个常数进行或运算构成oflag*
参数(这些常数定义在< fcntl . h >头文件中, 在这三个常数中应当只指定一个):
O_RDONLY 只读打开
O_WRONLY 只写打开
O_RDWR 读、写打开
第三个可选参数:
O_APPEND 每次写时都加到文件的尾端。
O_CREAT 若此文件不存在则创建它。使用此选择项时,需同时说明第三个参数mode,用其说明该新文件的存取许可权位。
O_EXCL 如果同时指定了O_CREAT,而文件已经存在,则出错。这可测试一个文件是否存在。
O_TRUNC 如果此文件存在,而且为只读或只写成功打开,则将其长度截短为0。
O_NONBLOCK 如果pathname指的是一个FIFO、一个块特殊文件或一个字符特殊文件,则此选择项为此文件的本次打开操作和后续的I /
O操作设置非阻塞方式。
O_SYNC 使每次write都等到物理I / O操作完成。
读文件(read)
#include <unistd.h>
ssize_t read(int fd, void *buff, size_t nbytes) ;
返回:读到的字节数,若已到文件尾为0,若出错为-1
写文件(write)
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t nbytes) ;
- 返回:若成功为已写的字节数,若出错为-1
- 对于普通文件,写操作从文件的当前位移量处开始。如果在打开该文件时,指定了O_APPEND选择项,则在每次写操作之前,将文件位移量设置在文件的当前结尾处。在一次成功写之后,该文件位移量增加实际写的字节数。
查权限
char* pargv[4]={"ls","-l","file1",NULL};
显示文件权限 execv("/bin/ls",pargv);
- 所以查询文件权限只需要:
1.pargv[2]改为待操作的文件名
2.执行execv("/bin/ls",pargv);
由于进程执行完execv后会退出而无法执行其他逻辑,于是fork一个子进程来作查权限的操作,主进程调用wait等子进程结束即可。
int p =fork();
if(p==0)
check_file_mod();
else
wait(NULL);
改权限chmod
- linux下的文件权限分三级:owner,group,others三类。每类占权限位的三位。
- r 表示可读取,w 表示可写入,x 表示可执行,X 表示只有当该档案是个子目录或者该档案已经被设定过为可执行。
- 其中:r=4,w=2,x=1
例如:若要rwx属性则4+2+1=7;
若要rw-属性则4+2=6;
若要r-x属性则4+1=7。 - 常见权限:
-rw------- (600) – 只有属主有读写权限。
-rw-r–r-- (644) – 只有属主有读写权限;而属组用户和其他用户只有读权限。
-rwx------ (700) – 只有属主有读、写、执行权限。
-rwxr-xr-x (755) – 属主有读、写、执行权限;而属组用户和其他用户只有读、执行权限。
-rwx–x--x (711) – 属主有读、写、执行权限;而属组用户和其他用户只有执行权限。
-rw-rw-rw- (666) – 所有用户都有文件读、写权限。这种做法不可取。
-rwxrwxrwx (777) – 所有用户都有读、写、执行权限。更不可取的做法。
lseek调用
每个打开的文件都有一个与其相关联的“当前文件位移量”。它是一个非负整数,用以度量从文件开始处计算的字节数。通常,读、写操作都从当前文件位移量处开始,并使位移量增加所读或写的字节数。按系统默认,当打开一个文件时,除非指定O_APPEND选择项,否则该位移量被设置为0。
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence) ;
参数offset 的解释与参数whence的值有关
若whence是SEEK_SET,则将该文件的位移量设置为距文件开始处offset 个字节
若whence是SEEK_CUR,则将该文件的位移量设置为其当前值加offset, offset可为正或负
若whence是SEEK_END,则将该文件的位移量设置为文件长度加offset, offset可为正或负
具体代码:
/*
1.
open 打开文件
creat 创建新文件
close 关闭文件描述字
read 读文件
write 写文件
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
int C_fd; //文件描述符
char filename[100]; //文件名
int isopen = 0; //打开状态
char *pargv[4] = {"ls", "-l", NULL, NULL};
void Open_Creat_file()
{
printf("请输入要打开/创建的文件名: ");
scanf("%s", filename);
C_fd = open(filename, O_RDWR, 0666);
if (C_fd >= 0)
{
isopen = 1, printf("%s已存在,打开成功\n", filename);
pargv[2] = (char *)malloc(50);
strcpy(pargv[2], filename);
}
else
{
C_fd = open(filename, O_CREAT, 0666);
if (C_fd >= 0)
isopen = 1, printf("%s不存在,新建成功\n", filename);
else
isopen = 0, printf("打开/新建%s失败\n", filename);
}
//close(fd);
}
void read_file()
{
if (!isopen)
{
printf("没有打开的文件,请先打开一个文件\n");
return;
}
else
printf("当前处理的文件是:%s\n", filename);
char buffer[100];
lseek(C_fd, 0, SEEK_SET); //从头开始读
int t = read(C_fd, buffer, 1024);
if (t != -1)
printf("文件内容为:%s\n", buffer);
else
printf("读取失败\n");
}
void write_file()
{
if (!isopen)
{
printf("没有打开的文件,请先打开一个文件\n");
return;
}
else
printf("当前处理的文件是:%s\n", filename);
char buffer[1024];
printf("请输入待写入内容:\n");
scanf("%s", buffer);
int t = write(C_fd, buffer, strlen(buffer));
if (t == -1)
printf("写入失败!\n");
else
printf("写入成功!\n");
}
void change_file_mod()
{
if (!isopen)
{
printf("没有打开的文件,请先打开一个文件\n");
return;
}
else
printf("当前处理的文件是:%s\n", filename);
int new_mode;
printf("输入新的模式(十进制)");
scanf("%d", &new_mode);
int mode_u = new_mode / 100;
int mode_g = new_mode / 10 % 10;
int mode_o = new_mode % 10;
new_mode = (mode_u * 8 * 8) + (mode_g * 8) + mode_o; //八进制转换
int t = chmod(filename, new_mode);
if (t == -1)
printf("改变模式失败!\n");
else{
printf("成功改变模式!\n");
printf("新模式:%d\n",new_mode);
}
}
void check_file_mod()
{
if (!isopen)
{
printf("没有打开的文件,请先打开一个文件\n");
return;
}
else
printf("当前处理的文件是:%s\n", filename);
printf("文件权限为");
int t = execv("/bin/ls", pargv);
if (t == -1)
printf("查看失败\n");
}
int main()
{
printf("-----------------CC_File_Tools--------------\n");
printf("1.打开(不存在则新建) 2.写文件 3.读文件 \n");
printf("4.改权限 5.查权限 0.退出 \n");
//printf("------------------------------------\n");
int choice = -1;
while (1)
{
printf("-------------请输入选择:-----------\n");
scanf("%d", &choice);
switch (choice)
{
case 0:
{
printf("\n\t感谢使用!\n\n");
return 0;
}
case 1:
{
Open_Creat_file();
break;
}
case 2:
{
write_file();
break;
}
case 3:
{
read_file();
break;
}
case 4:
{
change_file_mod();
break;
}
case 5:
{
int p =fork();
if(p==0)
check_file_mod();
else
wait(NULL);
break;
}
default:
{
printf("您的输入有误,请重新输入!!!\n");
}
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具