日期:2014-05-16  浏览次数:20953 次

unix/linux下拷贝文件和目录程序

目的:由于linux下不提供拷贝文件或者目录的函数,很不方便!因此,提供一个封装的函数实现拷贝文件或者目录(带目录内容),实现类似cp -r 的功能,支持相对路径和绝对路径输入。
申明:代码不代表最优的实现,经初步测试没有问题,如有BUG自行修改!

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>

int CopyFileExt(char* dest,char* src);
int main(int argc,char** argv)
{
	/*
	int ret=0;
	ret = unlink("/home/caojianping/caotest");
	printf("unlink return %d\n",ret);
	printf("ERROR:%s\n",strerror(errno));

	DelFile("/home/caojianping/caotest");
	*/
	if(argc != 3)
	{
		printf("Usage: copy dest src\n");
		return -1;
	}
	CopyFileExt(argv[1],argv[2]);

	return 0;
}


// 目的和源可以是目录也可以是文件
// dest == 文件, src == 文件, 删除dest文件,拷贝src文件到dest文件
// dest == 目录, src == 文件, 拷贝文件到dest目录下,如有同名文件,覆盖之
// dest == 目录, src == 目录, 拷贝src目录内容到dest目录下作为子目录(包括其内容)
// dest == 文件, src == 目录, 删除dest文件,拷贝src目录到dest命名的目录
// 返回值:0代表 OK,<0 出错
int CopyFileExt(char* dest,char* src)
{
	struct stat statbuf;
	struct dirent *dirp;
	DIR *dp;
	int ret;
	int destFile;	// 目标是文件标志 0表示目录,1表示文件
	int srcFile;	// 源是文件标志 0表示目录,1表示文件
	char destFull[256];		//存储全路径
	char srcFull[256];		//存储全路径
	
	// get the fullpath
	if(dest[0]!='/')   
	{
		getcwd(destFull,sizeof(destFull));
		strncat(destFull,"/",sizeof(destFull));
		strncat(destFull,dest,sizeof(destFull));
	}
	else
	{
		strncpy(destFull,dest,sizeof(destFull));
	}
	if(destFull[strlen(destFull)-1] == '/')   // 去掉路径后缀
	{
		destFull[strlen(destFull)-1] = '\0';
	}

	if(src[0]!='/')   
	{
		getcwd(srcFull,sizeof(srcFull));
		strncat(srcFull,"/",sizeof(srcFull));
		strncat(srcFull,src,sizeof(srcFull));
	}
	else
	{
		strncpy(srcFull,src,sizeof(srcFull));
	}
	if(srcFull[strlen(srcFull)-1] == '/')   // 去掉路径后缀
	{
		srcFull[strlen(srcFull)-1] = '\0';
	}


	if(lstat(destFull,&statbuf) < 0)
	{
		return -1;
	}
	if(S_ISDIR(statbuf.st_mode)== 0)   
	{
		destFile=1;       // file
	}
	else
	{
		destFile=0;       // directory
	}
	if(lstat(srcFull,&statbuf) < 0)
	{
		return -1;
	}
	if(S_ISDIR(statbuf.st_mode)== 0)   
	{
		srcFile=1;       // file
	}
	else
	{
		srcFile=0;       // directory
	}
	
	// src is file
	if(srcFile) 
	{
		FILE *fpdest;
		FILE *fpsrc;

		if(!destFile) 
		{
			char destpath[256];
			strncpy(destpath,destFull,255);
			char *truename = strrchr(srcFull,'/');
			if(truename)
			{
				strncat(destpath,truename,255);
			}
			fpdest = fopen(destpath,"w");
		}
		else
		{
			fpdest = fopen(destFull,"w");
		}

		if(fpdest==NULL)
		{
			return -2;
		}
		fpsrc = fopen(srcFull,"r");
		if(fpsrc==NULL)
		{
			return -2;
		}
		//copy file
		char buf[1024];
		int size;
		int offset=0;
		do
		{
			size = fread (buf,1,sizeof(buf),fpsrc);
			if(size > 0)
			{
				fwrite(buf,1,size,fpdest);
			}
		}
		while (!feof(fpsrc));
		fclose(fpdest);
		fclose(fpsrc);
	}
	else   // src is directory
	{
		if(destFile)   // dest is a file, override it
		{
			remove(destFull);
			mkdir(destFull,S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
		}

		dp = opendir(srcFull);
		if(dp == NULL)
		{
			return -2;
		}

		char destpath[256];
		strncpy(destpath,destFull,255);

		char *dirname = strrchr(srcFull,'/');
		if(dirname)
		{
			strncat(destpath,dirname,255);
		}
		mkdir(destpath,S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);   // 

		while((dirp = readdir(dp)) != NULL)
		{
			if(strcmp(dirp->d_name,".")==0 || strcmp(dirp->d_name,"..")==0)
			{
				continue;
			}

			char srcpath[256];
			strncpy(srcpath,srcFull,255);
			strncat(srcpath,"/",255);
			strncat(srcpath,dirp->d_name,255);
			CopyFileExt(destpath,srcpath);
		}
		closedir(dp);
	}

}