Linux系统编程之模拟命令cp

本文介绍了一个简单的Linux环境下模拟cp命令的程序实现。该程序能够复制文件到文件或目录,也能处理目录间的复制,并支持基本的命令行选项如-r、-l和-s。通过此程序加深了对Linux文件操作的理解。

最近在学习linux环境编程,用学到的文件编程写了一个模拟命令 cp的代码,当然有很多不足之处,但是基本功能都实现了。 文件编程用到的函数不明白的可以百度。其实学这个也只是为了加深对Linux系统的理解。代码有什么问题请回复,方便大家交流学习。

#include <unistd.h>

#include <stdio.h>

#include <stdlib.h>

#include <dirent.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <string.h>

#include <fcntl.h>

#define BUFFERSIZE 10000

int isdir(char *src)

{



    struct stat is_dir;

    //lstat函数把源文件名的文件类型和存储权限传给stat结构体中的st_mode变量 

    lstat(src, &is_dir);

    //S_ISDIR函数判断该文件是不是目录文件 

    if(S_ISDIR(is_dir.st_mode))

    {

        return 1;

    }

    return 0;

}

//文件拷贝到文件 或文件拷贝到目录下 

int copyF2F(char *src_file, char *dest_file)

{

    int in_fd, out_fd, n_chars;



    char buf[BUFFERSIZE];

    //如果目的地址是目录,则默认在该目录下创建一个与源文件同名的文件   

    if(isdir(dest_file))

    {

        char c;

        char temp[10] = {'\0'};

        char r_temp[10] = {'\0'};

        int n = strlen(src_file);

        int m = 0;

        //记录源文件最后一个'/'之后的内容 

        while((c = src_file[n-1]) != '/')

        {

            //用temp数组存下来 

            temp[m] = c;

            m++;

            n--;

        }

        int j = 0;

        //由于temp数组存下来的字符是反的,所以反转一下字符 

        for(int i = strlen(temp)-1; i >=0; i--)

        {

            r_temp[j] = temp[i];

            j++;

        }

        r_temp[j] = '\0';

        //将源文件的最后的文件名和目的文件目录拼接起来 

        strcat(dest_file, r_temp);

    }

    //打开源文件,获取到文件描述符,失败返回-1 

    if((in_fd = open(src_file, O_RDONLY)) == -1)

    {

        printf("%s is error", src_file);

        return 1;

    }

    //打开目的文件,获取文件描述符,失败返回-1,注意此时需要写的权限所以参数应该有O_WRONLY,并且如果不存在需要有权限创建。具体的函数用法参照上之前写的文件I/O编程博客 

    if((out_fd = open(dest_file, O_WRONLY | O_CREAT, 0644)) == -1)

    {

        printf("open is error");

        return 1;

}

    //现在源文件和目的文件的文件描述符都获取到了,开始复制。read函数第一个参数代表要读出的文件描述符,第二个参数代表存数据的数组首地址,第三个参数代表要读出多少个字节。读取成功返回读取的字节数,有错返回-1 

    if((n_chars = read(in_fd, buf, BUFFERSIZE))>0)

    {

        //写入目标文件中。错误返回-1 

        if(write(out_fd, buf, n_chars)<0 )

        {

            printf("%s write error", dest_file);

            return 1;

        }

    }

    //close函数用于关闭文件,打开文件了记得关 

    if(close(in_fd) == -1 || close(out_fd) == -1)

    {

        printf("error");

        return 1;

    }

    return 0;

}

//目录拷贝到目录下 

int copyD2D(char *src_dir, char *dest_dir)

{

    //用来获取打开文件目录时返回的指针 

    DIR *dp = NULL;

    struct dirent *dirp;

    char tempDest[256];

    char tempSrc[256];

    strcpy(tempDest, dest_dir);

    strcpy(tempSrc, src_dir);

    //opendir打开文件目录,返回NULL代表打开失败 

    if((dp = opendir(src_dir)) == NULL)

    {

        return 1;

    }

    else

    {

        //readdir()返回参数dir目录流的下个目录进入点 

        while((dirp = readdir(dp)))

        {

            if(isdir(dirp->d_name))  //d_name是文件的名称 

            {

                strcat(tempDest, dirp->d_name);     

                strcat(tempSrc, dirp->d_name);

                //将目录中的文件拷贝到另一个目录中 

                copyF2F(tempSrc, tempDest);

                //把tempDest和tempSrc重新初始化成目录名 

                strcpy(tempDest, dest_dir);

                strcpy(tempSrc, src_dir);

            }

        }

        //关闭打开的目录 

        closedir(dp);

        return 0;



    }

}



int main(int argc, char * argv[])

{

    int c, flag = 0;

    while((c = getopt(argc, argv, "rRls"))!=-1)

    {

        switch(c)

        {

            //选项为-R或-r时,执行目录之间的拷贝 

            case 'R':

            case 'r':

                copyD2D(argv[2], argv[3]);

                flag = 1; 

                break;

            //选项为-l时,创建链接 

            case 'l':

                if(isdir(argv[2]))

                {

                    printf("dir can't create a link");

                    exit(1);

                }

                if(link(argv[2], argv[3])==0)

                {

                    return 0;

                }

                else

                {

                    printf("create a link failed");

                }

                flag = 1;

                break;

            case 's':

                if(isdir(argv[2]))

                {

                    printf("dir can't create a symlink");

                }

                if((symlink(argv[2], argv[3])) == 0)

                {

                    return 0;

                }

                else

                {

                    printf("create a symlink failed");

                }

                flag = 1;

                break;

        }

    }

    if(flag == 0)

    {

        copyF2F(argv[1], argv[2]);

    }

    return 0; 

}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值