home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / c_spec / sources / mv.c < prev    next >
C/C++ Source or Header  |  1986-02-20  |  5KB  |  216 lines

  1. #include <stdio.h>
  2. #include <errno.h>
  3.  
  4. /*    MV.C        A Unix style rename function. Useage is
  5.  *
  6.  *            mv <file|directory> [filelist] <file|directory>
  7.  *
  8.  *    [filelist] may be present only if the rightmost argument is
  9.  *    a directory. If the file already exists, it is deleted.
  10.  *
  11.  *    -i    Verfify before overwriting an existing file
  12.  *    -e    Do not echo actions to screen as they are done (this will
  13.  *        make cp behave like the unix version, which is silent).
  14.  *
  15.  *    Exit status:    0 on success, 1 if a file couldn't be moved.
  16.  */
  17.  
  18. extern char    *cpy    (char*, char*);
  19. extern void    perror    (char*);
  20.  
  21. /*---------------------------------------------------------------------*/
  22.  
  23. int    Verify = 0;    /* Verify before overwriting existing file     */
  24. int    Echo   = 1;    /* Say what we're doing as we do it           */
  25.  
  26. /*---------------------------------------------------------------------*/
  27.  
  28. #define E(str)        fprintf(stderr, "%s\n", str)
  29. #define exists(file)    (!access(file,0))
  30.  
  31. /*---------------------------------------------------------------------*/
  32.  
  33. args(argc, argv)
  34. char    **argv;
  35. {
  36.     /*    Process command line arguments. If -i iv found set
  37.      *    Verify true, if -e is found set Echo false. Return
  38.      *    1 if we found an argument, 0 otherwise
  39.      */
  40.  
  41.     register char    *p;
  42.  
  43.     if( argv[1][0] == '-' )
  44.     {
  45.         if( --argc < 3 )
  46.             usage("Too few arguments");
  47.  
  48.         for( p = *++argv + 1 ; *p ; p++ )
  49.         {
  50.             if      ( *p == 'i' )        Verify = 1;
  51.             else if ( *p == 'e' )        Echo   = 0;
  52.             else    usage("Illegal argument %c", *p );
  53.         }
  54.  
  55.         return 1;
  56.     }
  57.  
  58.     return 0;
  59. }
  60.  
  61. /*---------------------------------------------------------------------*/
  62.  
  63. overwrite(targ)
  64. char    *targ;
  65. {
  66.     /*    Return true if a file exists and we should overwrite
  67.      *    it. If Verfify is set, ask the user.
  68.      */
  69.  
  70.     if( exists( targ ))
  71.     {
  72.         /* Target file exists */
  73.  
  74.         if( Verify )
  75.         {
  76.             fprintf(stderr,"Mv: %s exists, overwrite (y/n)?",
  77.                             targ);
  78.             if( getchar() == 'n' )
  79.             return 0;
  80.         }
  81.  
  82.         if( unlink(targ) < 0 )    /* Delete the target file */
  83.         {
  84.             fprintf(stderr,
  85.                 "File marked read only or is directory\n" );
  86.             return 0;
  87.         }
  88.     }
  89.  
  90.     return 1;
  91. }
  92.  
  93. /*---------------------------------------------------------------------*/
  94.  
  95. char        *get_fname( src )
  96. register char    *src;
  97. {
  98.     /* Return a pointer to the filename part of src */
  99.  
  100.     register char    *start ;
  101.  
  102.     for(start = src ; *src ; src++ )
  103.          if( *src == '/' || *src == '\\' )
  104.             start = src + 1;
  105.  
  106.     return( start );
  107. }
  108.  
  109. /*---------------------------------------------------------------------*/
  110.  
  111. main(argc, argv)
  112. char    **argv;
  113. {
  114.     char        targ[128];
  115.     register char    *end = targ;
  116.     register int    moving_to_dir = 0;
  117.     int        err ;
  118.     int        exit_status   = 0;
  119.  
  120.     ctlc();
  121.     reargv(&argc, &argv);
  122.  
  123.     if( argc < 3 )
  124.         usage("Too few arguments");
  125.  
  126.     if( args(argc,argv) )    /* Process command line arguments */
  127.     {
  128.         argc--;
  129.         argv++;
  130.     }
  131.  
  132.     argc -= 2;    /* Remove the file and target names from argv */
  133.     argv++;
  134.  
  135.     /* Copy the target name into targ. If the target is a directory
  136.      * add a trailing slash as well. If it's not a directory and
  137.      * argc is > 1 then the command line syntax is wrong.
  138.      */
  139.  
  140.     end = cpy( targ, argv[argc] );
  141.  
  142.     if( isdir(targ) )
  143.     {
  144.         *end++ = '/';
  145.         moving_to_dir = 1;
  146.     }
  147.     else if( argc > 1 )
  148.         usage("Can't move multiple files into one file");
  149.  
  150.  
  151.     for(; --argc >= 0; argv++ )
  152.     {
  153.         if( moving_to_dir )
  154.         {
  155.             /* If we're moving to a directory append
  156.              * the source name onto the end of the
  157.              * target name.
  158.              */
  159.  
  160.             strcpy(end, get_fname(*argv) );
  161.         }
  162.  
  163.         /* If we're moving a file to itself, we're already
  164.          * done. Similarly if we are told not to overwrite
  165.          * an existing file, we're done.
  166.          */
  167.  
  168.         if( !strcmp(*argv, targ) )
  169.             continue;
  170.  
  171.         if( !overwrite(targ) )
  172.             continue;
  173.  
  174.         if( Echo )
  175.             printf("Moving: %20s to %s", *argv, targ );
  176.  
  177.         if( err = rename(targ, *argv) )
  178.         {
  179.             if( err == EXDEV )
  180.                 printf(": May not move to another disk\n");
  181.  
  182.             else if( err == ENOENT )
  183.                 printf(": %s not found\n", *argv );
  184.             else
  185.                 printf("Can't move to another directory or disk\n");
  186.  
  187.             exit_status = 1;
  188.         }
  189.         else if( Echo )
  190.             printf("\n");
  191.     }
  192.  
  193.     exit( exit_status );
  194. }
  195.  
  196. /*---------------------------------------------------------------------*/
  197.  
  198. usage(str, i)
  199. char    *str;
  200. {
  201.     E("Mv: Copyright (c) 1986, Allen I. Holub. All rights reserved.\n");
  202.     fprintf(stderr, str, i );
  203.     E("");
  204.     E("Usage: mv [-ie] oldname newname");
  205.     E("       mv [-ie] file  [... file] directory\n");
  206.     E("-i     ask before over-writing existing files");
  207.     E("-e     don't echo names as they're copied\n");
  208.     E("Rename a file (the top syntax above) or move a file or group");
  209.     E("of files to another directory. A directory may be renamed,");
  210.     E("but not moved to another directory. A target directory must");
  211.     E("be named (unlike the DOS copy command), . (the current directory)");
  212.     E("and .. (the parent directory) alone or in combination");
  213.     E("(ie. \"mv file ../..\"  or  \"mv /dir/file .\") are acceptable.");
  214.     exit(1);
  215. }
  216.