cp命令的实现
在 Unix/Linux下 cp 用来复制文件 ,用法是 $ cp source-file target-file 一. 函数介绍1. 创建/重写文件 creat#includeint fd = creat(const char * pathname, mode_t mode);如果文件不存在,就创建它 。如果存在就把它的内容清空 ,把文件长度设为 0 。2.
·
在 Unix/Linux下 cp 用来复制文件 ,用法是 $ cp source-file target-file
一. 函数介绍
1. 创建/重写文件 creat
#include<fcntl.h>
int fd = creat(const char * pathname, mode_t mode);
如果文件不存在,就创建它 。如果存在就把它的内容清空 ,把文件长度设为 0 。
2. 写文件 write
#include <unistd.h>
ssize_t result = write( int fd , void *buf , size_t amt);
write这个系统调用告诉内核将内存中指定的数据写入文件,如果不能写入或写入失败,返回-1;如果写入成功,返回写入的字节数。
注意:调用 write 后要检查返回值是否与要写入的相同
3. 得到文件信息 stat
stat可用来获取文件的权限 (man 2 stat 察看),stat 结构体如下:
其中: st_mode 即是文件的权限
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for file system I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
二.标准版本代码实现(版本一)
#include <stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<string.h>
#define BUFFERSIZE 4096
void oops(char * , char *);
int main(int ac , char *av[])
{
int in_fd , out_fd , n_chars;
char buf[BUFFERSIZE];
struct stat sb;
if( ac != 3)
{
fprintf(stderr,"usage: %s source destination \n",*av);
exit(1);
}
/*
* 如果 原文件 与 目标文件相同时
*/
if ( strcmp(av[1], av[2]) == 0 ){
fprintf(stderr,"cp: `%s' and `%s' are the same file.\n",
av[1], av[2]);
exit(1);
}
// 打开要复制的源文件
if((in_fd = open(av[1],O_RDONLY)) == -1)
oops("Can not open",av[1]);
/*
* stat函数可以获得文件的权限
*/
if(stat(av[1] , &sb ) == -1)
{
perror("stat");
exit(1);
}
// 创建要复制到的目的文件
if((out_fd = creat(av[2],sb.st_mode)) == -1)
oops("Can not creat ",av[2]);
while(( n_chars = read(in_fd , buf ,BUFFERSIZE )) > 0)
if(write( out_fd , buf , n_chars ) != n_chars)
oops("Write error to ",av[2]);
// 检查返回值是否与要写入的文件相同
if( n_chars == -1)
oops("Read error from ",av[1]);
if( close(in_fd) == -1 || close(out_fd) == -1)
oops("Error closing files ","");
return 0;
}
void oops(char *s1 , char *s2)
{
fprintf(stderr,"Error: %s ",s1);
perror(s2);
exit(1);
}
三.具有 -i 的代码实现(版本二)
标准的cp 命令会自动覆盖已经存在的文件,而不会给出任何提示。现在要实现 cp 的参数 -i ,即可以在覆盖前给出提示,得到确认才覆盖。
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdlib.h>
#include<string.h>
#include<sys/stat.h>
#define BUFFERSIZE 4096
void oops(char *, char *);
void usage();
int exists(char *filename);
int ok_to_replace(char *filename);
int main(int ac, char *av[])
{
int in_fd, out_fd, n_chars;
char buf[BUFFERSIZE];
char *src = NULL, *dest = NULL;
int i_option = 0;
struct stat sb;
// 检查参数
while( --ac )
{
if ( strcmp("-i", *++av) == 0 )
i_option = 1;
else if ( src == NULL)
src = *av;
else if ( dest == NULL )
dest = *av;
else
usage();
}
if ( src == NULL || dest == NULL )
usage();
if ( (in_fd=open(src, O_RDONLY)) == -1 )
oops("Cannot open ", src );
if(stat(src,&sb) == -1)
{
perror("stat");
exit(1);
}
/*
* 当原文件src存在时,且 i_option== 1 ,即参数有 -i ;以及存在目标文件
*/
if ( i_option != 0 && exists(dest) != -1 )
{
// 如果按下的是 n,则不复制,直接退出
if( !ok_to_replace(dest))
exit(-1);
}
if ( (out_fd=creat( dest, sb.st_mode)) == -1 )
oops("Cannot creat", dest);
// 复制文件
while ( (n_chars = read(in_fd , buf, BUFFERSIZE)) > 0 )
if ( write( out_fd, buf, n_chars ) != n_chars )
oops("Write error to ", dest);
if ( n_chars == -1 )
oops("Read error from ", src);
if ( close(in_fd) == -1 || close(out_fd) == -1 )
oops("Error closing files","");
return 0;
}
void oops(char *s1, char *s2)
{
fprintf(stderr,"Error: %s ", s1);
perror(s2);
exit(1);
}
void usage()
{
fprintf(stderr,"usage: cp [-i] source dest\n");
exit(1);
}
/*
* exists用于判断文件是否存在
*/
int exists(char *filename)
{
int fd = -1;
if ( (fd = open(filename, O_RDONLY)) )
close(fd);
return fd ;
}
/*
* ok_to_replace 用于显示错误及从stdin中读取数据
*/
int ok_to_replace(char *filename)
{
char ans[10]; // 用于保存字符 y / n
char c;
int retval = 0;
fprintf(stderr,"cp: Ok to replace `%s'? ", filename);
if ( scanf("%9s", ans) == 1 )
{
if ( *ans == 'y' || *ans == 'Y' )
retval = 1;
}
//消除掉 y 或者 n 后面的字符
while( ( c = getchar() ) != EOF && c != '\n' )
;
return retval;
}
更多推荐
已为社区贡献1条内容
所有评论(0)