编写一个类似于cp命令的程序,当使用该程序复制一个空洞文件的普通文件时,要求目标文件的空洞与源文件保持一致
首先需要编写一个函数来产生带有空洞的文件:
kongdong.c
/*##############################################
#
# Author: Lizhenggen - 762741539@qq.com
#
# QQ : 762741539
#
# Last modified: 2022-04-16 22:59
#
# Filename: kongdong.c
##############################################*/
#include <sys/stat.h>
#include <fcntl.h>
#include "tlpi_hdr.h"
int main(int argc, char *argv[])
{
int fd = -1;
char buf[100] = {0};
char writebuf[20] = "abcd";
int ret = -1;
fd = open("a.txt", O_RDWR|O_CREAT);
if (fd == -1) //文件描述符为-1则表示打开失败,
errExit("opening file %s", argv[1]);
ret = lseek(fd, 10, SEEK_SET);//将文件指针从文件开始的位置往后偏移10个字节。
ret = write(fd, writebuf, strlen(writebuf));
if(ret < 0 )
{
perror("write失败:\n");
}
else
{
printf("写入了%d个字符\n", ret);
}
return 0;
}
生成的空洞文件如下图所示:
然后编写copy函数:
/*##############################################
#
# Author: Lizhenggen - 762741539@qq.com
#
# QQ : 762741539
#
# Last modified: 2022-04-15 08:58
#
# Filename: copy.c
##############################################*/
#include <sys/stat.h>
#include <fcntl.h>
#include "tlpi_hdr.h"
#ifndef BUF_SIZE
#define BUF_SIZE 1024
#endif
int main(int argc, char *argv[])
{
int inputFd, outputFd, openFlags;
mode_t filePerms;
ssize_t numRead;
char buf[BUF_SIZE]; //定义一个大小为1024字节的缓存区
if (argc != 3 || strcmp(argv[1], "-h") == 0) //如果参数不为3或者第二个参数为-h则输出帮助信息
usageErr("%s old-file new-file\n", argv[0]);
inputFd = open(argv[1], O_RDONLY); //以只读的方式打开指定文件,并返回该文件描述符,未创建文件可以省略第三个参数
if (inputFd == -1) //文件描述符为-1则表示打开失败,
errExit("opening file %s", argv[1]);
openFlags = O_CREAT | O_WRONLY | O_TRUNC; //以只读方式打开指定文件,文件不存在则创建文件,文件存在则将其内容清空
filePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | //此参数设置了新创建文件的访问权限,该参数一定得是新创建的文件才会生效
S_IROTH | S_IWOTH; /* rw-rw-rw- */
outputFd = open(argv[2], openFlags, filePerms);
if (outputFd == -1)
errExit("opening file %s", argv[2]);
//新文件与旧文件的文件描述符均已生成
while ((numRead = read(inputFd, buf, BUF_SIZE)) > 0) //将指定文件的数据读到缓存区,缓存区至少为1024个字节,返回值为实际读取到的字节数
if (write(outputFd, buf, numRead) != numRead) //将数据从缓存区写入到已打开的文件,numRead是指欲写入的字节数,返回值为实际写入的数
fatal("write() returned error or partial write occurred");//当两值不等则是部分写入
if (numRead == -1) //-1表示读取失败
errExit("read");
if (close(inputFd) == -1) //显示关闭
errExit("close input");
if (close(outputFd) == -1) //显示关闭
errExit("close output");
exit(EXIT_SUCCESS);
}
编写Makefile用于编译两个文件:
LIBINCL = -I/apue/tlpi-book/lib
CPUBLIC = /apue/tlpi-book/lib/get_num.c /apue/tlpi-book/lib/error_functions.c
CFLAGS = -g
all : copy kongdong
copy : copy.c
gcc $(CFLAGS) -o copy copy.c $(LIBINCL) $(CPUBLIC) -lm -lc
kongdong : kongdong.c
gcc $(CFLAGS) -o kongdong kongdong.c $(LIBINCL) $(CPUBLIC) -lm -lc
make一下,运行相关程序以后得到b.txt文件
打开b.txt文件后得到与atxt一样的包含空洞的文件:
可以看到文件大小为14个字节,10字节空洞加上abcd四个字节: