zoukankan      html  css  js  c++  java
  • 编写自己的cp命令

      有时候要对整个目录做备份,修改cp1.c使得当两个参数都是目录时,把第一个目录中的所有文件复制到第二个目录中,文件名不变。那么该如何实现?
      我们先来看看cp1.c的实现方式,它从一个文件中读取数据然后写到另一个文件中,通过系统调用open(或者creat)、read、wirte和close来完成。从上面我们看出,cp1.c只是针对于一个文件进行的复制操作,而现在我们需要完成对整个目录的备份。参数由一个单独的文件(file)变成一个目录(directory),所以我们首先想到的就是要先进入到这个目录下,然后对该目录下的文件依次进行cp操作,那么这就涉及到了目录的操作,而我们在第三章ls命令的实现过程中,用到的就是对目录的操作,涉及到的系统调用包含有opendir、readdir和closedir。所以现在我们需要把两者用到的技术联系起来,以便完成对目录的备份工作。
      具体实现:
        1、命令行参数
          int argc、char *argv[]
        2、cp源、目的的类型判断
          src为dir,dst也必须是dir
          src为file,dst可以是anything
        3、目录操作
          opendir进入src目录下;
          while{
            readdir获得当前目录下的文件(或目录),递归判断是否还是目录,如果是继续深入;
            srcpath、dstpath获取,调用cp完成复制;
          }
          closedir完成目录复制
        4、cp实现
          in=open(src);out=creat(dst)
          while{
            read(in);
            write(out);
          }
          close(in);close(out)

    具体的代码如下:

     1 /** cp1.c
     2  *     version 1 of cp - uses read and write with tunable buffer size
     3  *
     4  *     usage: cp1 src dest
     5  */
     6 #include        <stdio.h>
     7 #include        <unistd.h>
     8 #include        <fcntl.h>
     9 
    10 #define BUFFERSIZE      4096
    11 #define COPYMODE        0644
    12 
    13 void oops(char *, char *);
    14 
    15 main(int ac, char *av[])
    16 {
    17         int     in_fd, out_fd, n_chars;
    18         char    buf[BUFFERSIZE];
    19                         /* check args     */
    20         if ( ac != 3 ){
    21                 fprintf( stderr, "usage: %s source destination
    ", *av);
    22                 exit(1);
    23         }
    24                         /* open files    */
    25 
    26         if ( (in_fd=open(av[1], O_RDONLY)) == -1 )
    27                 oops("Cannot open ", av[1]);
    28 
    29         if ( (out_fd=creat( av[2], COPYMODE)) == -1 )
    30                 oops( "Cannot creat", av[2]);
    31     
    32                         /* copy files    */
    33 
    34         while ( (n_chars = read(in_fd , buf, BUFFERSIZE)) > 0 )
    35                 if ( write( out_fd, buf, n_chars ) != n_chars )
    36                         oops("Write error to ", av[2]);
    37     if ( n_chars == -1 )
    38             oops("Read error from ", av[1]);
    39 
    40                         /* close files    */
    41 
    42         if ( close(in_fd) == -1 || close(out_fd) == -1 )
    43                 oops("Error closing files","");
    44 }
    45 
    46 void oops(char *s1, char *s2)
    47 {
    48         fprintf(stderr,"Error: %s ", s1);
    49         perror(s2);
    50         exit(1);
    51 }

     改进(添加目录判断)之后的具体实现:

      1 /** cp2.c
      2  ** ------------------------------------------------------------
      3     cp2.c is a
      4     revised version of cp1.c that can copy an entire directory
      5     file by file to a second directory.  It also supports some
      6     of the features required by earlier exercises.
      7 
      8  ** ------------------------------------------------------------
      9  **
     10  ** 
     11  *     A version of cp1.c that works if src or dest name directories
     12  *     (but not if src is a directory and dest is not)
     13  *
     14  *     usage: cp1 src dest
     15  *     If dest names a directory, then copy src to dest/src
     16  *     If src  names a directory, then copy all files in src to dest
     17  *        If src is a directory and dest is NOT a directory, quit
     18  *     Note: if src has a leading path, then only use last component
     19  *     
     20  *    build: cc sol03.14.c -o sol03.14
     21  */
     22 #include        <stdio.h>
     23 #include    <stdlib.h>
     24 #include        <unistd.h>
     25 #include        <fcntl.h>
     26 #include    <sys/stat.h>
     27 #include    <string.h>
     28 #include    <dirent.h>
     29 
     30 #define BUFFERSIZE      4096
     31 /*
     32  * note: the real copy takes the mode of the copy from
     33  *       the mode of the source.  
     34  */
     35 #define COPYMODE        0644
     36 
     37 void oops(char *, char *);
     38 void *emalloc(size_t);
     39 
     40 int
     41 main(int ac, char *av[])
     42 {
     43         if ( ac != 3 ){
     44                 fprintf( stderr, "usage: %s source destination
    ", *av);
     45                 exit(1);
     46         }
     47 
     48     /*
     49      * if source is a dir, then the dest has to be, too
     50      */
     51 
     52     if ( isadir(av[1]) ){
     53         if ( isadir(av[2]) )
     54             copydir(av[1], av[2]);
     55         else {
     56             fprintf(stderr,"cp1: %s is not a directory
    ", av[2]);
     57             exit(1);
     58         }
     59     }
     60     /*
     61      * if source is not a dir, then the dest can be anything
     62      */
     63     else
     64         do_copy( av[1], av[2] );
     65     return 0;
     66 }
     67 
     68 /*
     69  * copydir()
     70  *   loops through all files in srcdir, copying each to destdir
     71  *   uses do_copy but builds the paths here
     72  *   Note: this function skips subdirectories of srcdir
     73  */
     74 copydir(char *srcdir, char *destdir)
     75 {
     76     char           *srcpath, *destpath;
     77     DIR           *dir_ptr;
     78     struct dirent  *direntp;
     79 
     80     srcpath  = (char *) emalloc(strlen(srcdir)+1+MAXNAMLEN+1);
     81     destpath = (char *) emalloc(strlen(destdir)+1+MAXNAMLEN+1);
     82     if ( (dir_ptr = opendir(srcdir)) == NULL )
     83         oops("Cannot open directory", srcdir);
     84 
     85     /*
     86      * loop through all items in src dir
     87      *  Do not copy directories, and report that so user
     88      *  realizes not all the items are copied.
     89      */
     90     while( ( direntp = readdir(dir_ptr)) != NULL )
     91     {
     92         sprintf(srcpath,"%s/%s", srcdir, direntp->d_name);
     93         if ( isadir(srcpath) ){
     94             if ( strcmp(direntp->d_name,".") != 0 &&
     95                  strcmp(direntp->d_name,"..") != 0 )
     96                 printf("skipping directory %s
    ", srcpath);
     97             continue;
     98         }
     99         sprintf(destpath, "%s/%s", destdir, direntp->d_name);
    100         do_copy( srcpath, destpath );
    101     }
    102     closedir(dir_ptr);
    103     free(srcpath);
    104     free(destpath);
    105 }
    106 
    107 /*
    108  * copies a file from src to dest
    109  * If dest is a directory, then do_copy() copies to
    110  * a file in dest with the name taken from the filename for
    111  * src
    112  */
    113 do_copy(char *src, char *dest)
    114 {
    115         int     in_fd, out_fd, n_chars;
    116         char    buf[BUFFERSIZE];
    117     char    *destfilename;
    118     char    *make_destfilename(char*,char*);
    119 
    120     destfilename = make_destfilename(src, dest);
    121 
    122     /*
    123      * open files
    124      */
    125 
    126         if ( (in_fd=open(src, O_RDONLY)) == -1 )
    127                 oops("Cannot open ", src);
    128 
    129         if ( (out_fd=creat( destfilename, COPYMODE)) == -1 )
    130                 oops( "Cannot creat", destfilename);
    131     
    132     /*
    133      * copy files
    134      */
    135 
    136         while ( (n_chars = read(in_fd , buf, BUFFERSIZE)) > 0 )
    137                 if ( write( out_fd, buf, n_chars ) != n_chars )
    138                         oops("Write error to ", destfilename);
    139     if ( n_chars == -1 )
    140             oops("Read error from ", src);
    141 
    142     /*
    143      * close files
    144      */
    145 
    146         if ( close(in_fd) == -1 || close(out_fd) == -1 )
    147                 oops("Error closing files","");
    148 }
    149 
    150 void oops(char *s1, char *s2)
    151 {
    152         fprintf(stderr,"Error: %s ", s1);
    153         perror(s2);
    154         exit(1);
    155 }
    156 
    157 /*
    158  * if dest is a directory, then combine src and dest
    159  * (see header to this program)
    160  */
    161 
    162 char *
    163 make_destfilename(char *src, char *dest)
    164 {
    165     struct stat info;
    166     char   *srcfilename;
    167     char   *rv;
    168 
    169     if ( stat(dest, &info) == -1 )    /* let someone else handle this */
    170         return dest;
    171 
    172     if ( ! S_ISDIR(info.st_mode) )    /* ok to copy to other types    */
    173         return dest;
    174 
    175     /* find last component of source name */
    176     if ( (srcfilename = strrchr(src, '/')) != NULL )
    177         srcfilename++;
    178     else
    179         srcfilename = src;
    180 
    181     /* use that to construct target name */
    182     rv = emalloc(strlen(srcfilename) + strlen(dest) + 2);
    183     sprintf(rv, "%s/%s", dest, srcfilename);
    184 
    185     return rv;
    186 }
    187 
    188 void *
    189 emalloc(size_t n)
    190 {
    191     void *rv = malloc(n);
    192     if ( rv == NULL )
    193         oops("Out of memory","");
    194     return rv;
    195 }
    196 /*
    197  * boolean: tells if arg names a directory
    198  */
    199 isadir(char *str)
    200 {
    201     struct stat info;
    202 
    203     return ( stat(str,&info) != -1 && S_ISDIR(info.st_mode) );
    204 }
  • 相关阅读:
    字体填充
    通过浏览器直接打开Android应用程序
    IE能够打开网页 可是chrome和火狐打不开网页解决的方法
    openGl学习之加入颜色
    站点变为黑白
    POJ 3169 Layout (图论-差分约束)
    自己定义控件-GifView
    标准C函数库的使用方法
    MyEclipse中jsp的凝视报错解决
    Surrounded Regions
  • 原文地址:https://www.cnblogs.com/xymqx/p/3714808.html
Copyright © 2011-2022 走看看