编写一个类似于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;
}

生成的空洞文件如下图所示:
abcd前面的乱码即为空洞
然后编写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四个字节:
在这里插入图片描述

posted @ 2022-04-16 23:51  一颗蘋果  阅读(26)  评论(0编辑  收藏  举报