#include "unistd.h" //所需头文件定义
#include "string.h"
#include "dirent.h"
#include "utime.h"
#include "stdio.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#define MAX_PATH 1024 // 定义最大路径长度
void copy_data(char* spath,char* dpath) //复制一个文件
{
int nbyte ; //读出n个字节
int pDir_s,pDir_d ; //源文件句柄pDir_s, 目标文件句柄pDir_d
char buf[BUFSIZ] ; //文件内容缓冲区
struct stat file_stat ; //文件属性 file_stat
struct utimbuf mod_time; //文件时间属性
stat(spath,&file_stat) ; //读取源文件属性
if((pDir_s=open(spath,0)) == -1) //打开源文件
{
printf("无法打开文件 %s,权限不足!\n",spath) ; //源文件不可读
exit(0);
}
pDir_d=creat(dpath,0777); //创建一个目标文件,可读可写,可执行
while((nbyte = read(pDir_s,buf,BUFSIZ)) > 0) //从源文件读取内容,写入目标文件
{
if(write(pDir_d,buf,nbyte) != nbyte)
{
printf("写数据出现异常错误!\n") ; //写数据出错,退出
exit(0);
}
}
mod_time.actime = file_stat.st_atime ; //修改目标文件时间属性,保持和源文件一致
mod_time.modtime = file_stat.st_mtime ;
utime(dpath,&mod_time) ;
chmod(dpath,file_stat.st_mode); //修改目标文件权限,保持和源文件一致
close(pDir_s) ; //关闭文件句柄
close(pDir_d) ;
}
void mycp(char* source,char* des) //拷贝一个目录,以及目录下子目录和相应的文件
{
struct dirent* ent = NULL; //定义目录属性dirent
struct utimbuf mod_time; //定义目录时间属性变量
char spath[MAX_PATH] = "", dpath[MAX_PATH] = "" ; //源文件路径spath,目标文件路径dpath
DIR *pDir; //句柄
struct stat file_stat ; //文件或者目录属性变量file_stat
strcpy(spath,source) ;
strcpy(dpath,des) ;
pDir=opendir(source); //打开当前目录
while (NULL != (ent=readdir(pDir))) //循环读取文件或目录属性,遍历文件夹
{
if(strcmp(ent->d_name,"..")==0||strcmp(ent->d_name,".")==0) //遇到子目录'.'或父母录标记'..',继续
continue ;
if (ent->d_type == 4) //d_type = 4,表示当前为子目录
{
strcat(dpath,"/");
strcat(dpath,ent->d_name) ; //构建目标文件子目录路径
strcat(spath,"/");
strcat(spath,ent->d_name) ; //构建源文件子目录路径
stat(spath,&file_stat); //读取源文件子目录属性
mkdir(dpath,0777); //创建目标文件子目录,可读可写,可执行
mod_time.actime = file_stat.st_atime ;
//修改目标子目录时间属性和源子目录时间属性保持一致
mod_time.modtime = file_stat.st_mtime ;
mycp(spath,dpath); //递归拷贝子目录
chmod(dpath,file_stat.st_mode); //修改目标子目录权限,保持和原子目录权限一致
utime(dpath, &mod_time) ; //设置目标子目录时间属性,保持和原子目录一致
strcpy(dpath,des); //还原路径
strcpy(spath,source) ;
}
else { //d_type != 4,是文件,调用copy_data直接拷贝
strcat(dpath,"/"); //构建目标文件路径
strcat(dpath,ent->d_name) ;
strcat(spath,"/"); //构建源文件路径
strcat(spath,ent->d_name) ;
copy_data(spath,dpath); //拷贝一个文件
strcpy(dpath,des); //还原路径
strcpy(spath,source);
}
}
}
int main(int argc,char* argv[])
{
DIR *pDir;
struct stat file_stat ;
struct utimbuf mod_time; //定义目录时间属性变量
if(argc < 2) //必须有2个参数, 一个为源文件夹路径,一个为目标文件夹路径
{
printf("argument error!\n");
return 0 ;
}
printf("Copy start!\n"); //提示开始copy
if (pDir = opendir(argv[1])==NULL)
{
printf("The file you want to copy do not exist!\n");
return 0;
}
stat(argv[1],&file_stat) ; //读取原路径文件夹属性
if(pDir = opendir(argv[2])==NULL); //如果目标文件夹不存在,则新建目标文件夹
mkdir(argv[2],file_stat.st_mode);
mod_time.actime = file_stat.st_atime ; //修改目标文件时间属性,保持和源文件一致
mod_time.modtime = file_stat.st_mtime ;
utime(argv[2], &mod_time) ; //设置目标子目录时间属性,保持和原子目录一致
mycp(argv[1],argv[2]) ;//完成copy的函数
printf("Copy complete!\n") ;//提示完成copy
return 0;
}