C实现Linux中copy功能/*
mycp.c
*/
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>
#include<dirent.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<getopt.h>
#include<stdbool.h>
#define BUFFERSIZE 1024
#define COPYMORE 0644
/*⽤于处理从⽬录⽂件复制到⽬录⽂件的操作,传⼊的参数应该是⽬录路径*/
int copyD2D(char *src, char *dest);
/*⽤于处理从⽂件复制到⽂件的操作,输⼊的参数是⽂件名*/
int copyF2F(char *src, char *dest);
/*判断filename是否是⽬录名*/
bool isdir(char *filename);
/*字符串反转*/
char *strrev(char *str);
/*main函数⽤于接收命令⾏传进来的参数,并判断是否符合规范。
然后根据不同的情况调⽤不同的⼦函数。*/
int main(int argc, char **argv)
{
/*
标记-r/-R选项,该选项代表递归复制⽂件夹
标记-l选项,-l选项代表创建硬链接
标记-s选项,-s选项代表创建符号链接
*/
bool opt_r = false;
bool opt_l = false;
字符串拷贝函数strcpy作用bool opt_s = false;
/*
⽤于记录源⽂件
⽤于记录⽬标⽂件
记录选项的字符
*/
char *src = NULL;
char *dest = NULL;
char c;
/*循环检测命令⾏参数中的选项*/
while((c = getopt(argc, argv, "rRls")) != -1)
{
switch(c)
{
case'R':
case'r':
opt_r = true;
break;
case'l':
opt_l = true;
break;
case's':
opt_s = true;
break;
}
}
/*命令⾏参数中应该有两个⽂件名。若没有,则输出提⽰,并终⽌程序*/
if (optind >= argc - 1)
{
printf("lack operator \n");
exit(1);
}
/
*从命令⾏参数中读取源⽂件和⽬标⽂件名*/
src = argv[optind];
dest = argv[optind + 1];
/*根据opt_l选项的真假,做相应操作。
若为真,则创建硬链接,使⽤link函数。*/
if (opt_l)
{
if (isdir(src))
{
printf("dirent canot build hard linker\n");
exit(1);
}
/*link 函数的返回值:若成功,则返回0;若出错,返回-1*/
if ((link(src, dest)) == 0)
{
return0;
}
else
{
printf("create hard linker error\n");
exit(1);
}
}
/*根据opt_s选项的真假,做相应操作。
若为真,则创建符号链接,使⽤symlink函数。*/
if (opt_s)
{
if(isdir(src))
{
printf("dirent cannot create soft linker\n");
exit(1);
}
if (symlink(src, dest) == 0)
{
return0;
}
else
{
printf("create soft linker error\n");
exit(1);
}
}
if (!isdir(src))
{
/
*若源⽂件src不是⽬录,直接调⽤copyF2F函数。*/
if ((copyF2F(src, dest)) == 0)
{
return0;
}
else
{
printf("copy file error\n");
exit(1);
}
}
else if(isdir(src))
{
if (!isdir(dest))
{
printf("Canot copy the dirent to a file\n");
exit(1);
}
/*若源⽂件src和⽬标⽂件dest都是⽬录,直接调⽤copyD2D函数。*/ else if(isdir(dest) && opt_r)
{
if (copyD2D(src, dest) != 0)
{
printf("copy catalog error\n");
exit(1);
}
else
{
return0;
}
}
else
{
printf("copy catalog need option -r\n");
exit(1);
}
}
else
{
printf("the operation is illegal\n");
exit(1);
}
return0;
}
/*该函数⽤于处理复制⽬录的情况*/
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函数打开src_dir⽬录,获得指向该⽬录名字的指针*/
if ((dp = opendir(src_dir)) == NULL)
{
return1;
}
else
{
while((dirp = readdir(dp)))
{
struct stat  file_stat;
if (!isdir(dirp->d_name))
{
/*将dirent结构中的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);
}
return0;
}
/*该函数通过read,write等基本的系统函数,完成⽂件的拷贝⼯作*/
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;
int n = strlen(src_file);
int m = 0;
/*读取源⽂件的最后⼀级⽂件名作为⽬标⽂件名*/
while((c = src_file[n-1]) != '/')
{
temp[m] = c;
m++;
n--;
}
r_temp = strrev(temp);
strcat(dest_file, r_temp);
}
/* 以可读模式打开源⽂件 */
if ((in_fd = open(src_file, O_RDONLY)) == -1)
{
printf("%s file read error!\n", src_file);
return1;
}
/* O_WRONLY代表以读写的⽅式打开⽬标⽂件,O_CREAT选项代表若⽂件不存在则创建,    COPYMORE = 0644,⽂件所有者可读可写,其他可读 */
if ((out_fd = open(dest_file, O_WRONLY | O_CREAT, COPYMORE)) == -1)
{
return1;
}
/* 通过read和write系统调⽤实现⽂件的复制 */
while ((n_chars = read(in_fd, buf, BUFFERSIZE)) > 0)
{
if (write(out_fd, buf, n_chars) != n_chars)
{
printf("%s file write error!\n", src_file);
return1;
}
if (n_chars == -1)
{
printf("%s file read error!\n", src_file);
return1;
}
}
if (close(in_fd) == -1 || close(out_fd) == -1)
{
printf("close file error\n");
return1;
}
return0;
}
/
*判断filename是否为⽬录⽂件*/
bool isdir(char *filename)
{
struct stat fileInfo;
if (stat(filename, &fileInfo) >= 0)
{
if (S_ISDIR(fileInfo.st_mode))
{
return true;
}
else
{
return false;
}
}
}
char *strrev(char *str)
{
int i = strlen(str) - 1, j = 0;
char ch;
while(i > j)
{
ch = str[i];
str[i] = str[j];
str[j] = ch;
i--;
j++;
}
return str;
}
运⾏结果:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。