home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / cenvi23.zip / COPY.CMM < prev    next >
Text File  |  1996-02-05  |  16KB  |  544 lines

  1. /*
  2.  * Copy.cmm
  3.  *
  4.  * A copy script for the CEnvi shell. It does what the DOS copy
  5.  * command does.
  6.  */
  7.  
  8. #include "netware.lib"
  9. #include "filename.lib"
  10.  
  11. usage()
  12. {
  13.   printf("Use the COPY command to copy one or more file(s) from one\n");
  14.   printf("location to another.\n");
  15.   printf("Syntax:\n");
  16.   printf("  COPY [drive][path] filename [+][,,][drive][path][filename] [/V]\n");
  17.   printf("where:\n");
  18.   printf("  drive/path/filename   Specifies the file to be copied.\n");
  19.   printf("  +                     Combines or appends files.\n");
  20.   printf("  + ,,                  Updates the time and date of a file.\n");
  21.   printf("  drive/path/filename   Specifies the target file name.\n");
  22.   printf("  /V                    Verifies that sectors written to the target\n");
  23.   printf("                        disk are recorded properly.\n");
  24.   exit(EXIT_FAILURE);
  25. }
  26.  
  27. /* ---------------------------------------------------------------------- */
  28.  
  29. /*
  30.  * Some DOS functions
  31.  */
  32. SetFileAttributes(pFileName,pAttributes)
  33. {
  34.    lReg.ah = 0x43;
  35.    lReg.al = 1;
  36.    lReg.cx = pAttributes;
  37.    if !defined(_DOS32_)
  38.       lReg.ds = segment(pFileName), lReg.dx = offset(pFileName);
  39.    else
  40.       lReg.dx = pointer(pFileName);
  41.    return interrupt(0x21,lReg);
  42. }
  43.  
  44. SetFileDateAndTime(pFileName,pTime)
  45. {
  46.    lSuccess = False;
  47.    // Open file to get a handle
  48.    lReg.ah = 0x3D;
  49.    lReg.al = 0x42;
  50.    if !defined(_DOS32_)
  51.       lReg.ds = segment(pFileName), lReg.dx = offset(pFileName);
  52.    else
  53.       lReg.dx = pointer(pFileName);
  54.    if ( interrupt(0x21,lReg,lRegout) ) {
  55.       lHandle = lRegout.ax;
  56.       // write date to file
  57.       undefine(lReg);
  58.       lReg.ah = 0x57;
  59.       lReg.al = 1;
  60.       lReg.bx = lHandle;
  61.       lTm = localtime(pTime);
  62.       lReg.cx = (lTm.tm_sec / 2)
  63.               | (lTm.tm_min << 5)
  64.               | (lTm.tm_hour << 11);
  65.       lReg.dx = lTm.tm_mday
  66.               | ((lTm.tm_mon+1) << 5)
  67.               | ((lTm.tm_year-80) << 9);
  68.       lSuccess = interrupt(0x21,lReg);
  69.       // close file
  70.       undefine(lReg);
  71.       lReg.ah = 0x3E;
  72.       lReg.bx = lHandle;
  73.       interrupt(0x21,lReg);
  74.    }
  75.    return lSuccess;
  76. }
  77.  
  78. DOSTimeFromCalendar(time)
  79. {
  80.   dos = DOSTimeStructFromCalendar(time);
  81.   return (dos.time<<16) | (dos.date);
  82. }
  83.  
  84. DOSTimeStructFromCalendar(time)
  85. {
  86.   tm = localtime(time);
  87.   dos.time = (tm.tm_sec/2) | (tm.tm_min<<5) | (tm.tm_hour<<11);
  88.   dos.date = tm.tm_mday | ((tm.tm_mon+1)<<5) | ((tm.tm_year-80)<<9);
  89.   return dos;
  90. }
  91.  
  92. GMDOSTimeStructFromCalendar(time)
  93. {
  94.   tm = gmtime(time);
  95.   dos.time = (tm.tm_sec/2) | (tm.tm_min<<5) | (tm.tm_hour<<11);
  96.   dos.date = tm.tm_mday | ((tm.tm_mon+1)<<5) | ((tm.tm_year-80)<<9);
  97.   return dos;
  98. }
  99.  
  100. #define GENERIC_WRITE 0x40000000
  101. #define FILE_SHARE_READ 0x01
  102. #define FILE_SHARE_WRITE 0x02
  103. #define OPEN_EXISTING 3
  104. #define INVALID_HANDLE_VALUE -1
  105.  
  106. /* ---------------------------------------------------------------------- */
  107.  
  108. verify = FALSE;
  109. source[0] = "";
  110. num_source = 0;
  111. target = "";
  112. doing_plus = FALSE;
  113. update_time = FALSE;
  114.  
  115. parse_command_line(argc,argv)
  116. {
  117.    for( i=1;i<argc;i++ )
  118.    {
  119.       if( argv[i][0]=='-' || argv[i][0]=='/' )
  120.       {
  121.          switch( toupper(argv[i][1]) )
  122.          {
  123.             default: usage();
  124.             case 'V': verify = TRUE; break;
  125.          }
  126.          continue;
  127.       }
  128.       if( argv[i][0]=='+' )
  129.       {
  130.          if( doing_plus ) {
  131.             printf("Already doing plus mode.\n");
  132.             exit(EXIT_FAILURE);
  133.          }
  134.          if( num_source==0 ) {
  135.               printf("You must specify a file, then you can use + to specify more.\n");
  136.               exit(EXIT_FAILURE);
  137.          }
  138.          doing_plus = TRUE;
  139.          if( argv[i][1] ) {
  140.             argv[i]++;
  141.             i--;
  142.          }
  143.          continue;
  144.       }
  145.       if( argv[i][0]==',' )
  146.       {
  147.          if( !doing_plus || argv[i][1]!=',' ) {
  148.             printf("To update a file's time, use \"+ ,,\".\n");
  149.             exit(EXIT_FAILURE);
  150.          }
  151.          update_time = TRUE;
  152.          doing_plus = FALSE;
  153.          continue;
  154.       }
  155.       // Have a filename
  156.       if( num_source==0 || doing_plus ) {
  157.          strcpy(source[num_source++],argv[i]);
  158.          doing_plus = FALSE;
  159.          continue;
  160.       }
  161.  
  162.       if( target[0]!='\0' ) {
  163.          printf("Too many target files specified.\n");
  164.          exit(EXIT_FAILURE);
  165.       }
  166.       strcpy(target,argv[i]);
  167.    }
  168.    if( doing_plus ) { printf("Extraneous plus.\n"); exit(EXIT_FAILURE); }
  169.    if( num_source==0 )
  170.      { printf("No source file specified.\n"); exit(EXIT_FAILURE); }
  171.    if( target[0]=='\0' ) target = ".";
  172. }
  173.  
  174. /*
  175.  * Copy a single file. When done, set the time to the old file's time
  176.  * stamps if update_time not set
  177.  */
  178. copy_file(source,target)
  179. {
  180.   strcpy(src,FullPath(source));
  181.   strcpy(tar,FullPath(target));
  182.  
  183.   if( !stricmp(src,tar) )
  184.     {
  185. // Same file!
  186.       if( update_time )
  187.         {
  188.           dir = Directory(target);
  189.           if( dir==NULL || GetArraySpan(dir)>0 )
  190.             {
  191.               printf("Copy_file: error, target should be a single file.\n");
  192.               return;
  193.             }
  194.  
  195.           curtime = time();
  196.           if( defined(_NWNLM_) )
  197.             {
  198.               tempcreate[0] = DOSTimeFromCalendar(curtime);
  199.               tempaccess[0] = DOSTimeFromCalendar(curtime);
  200.               tempdate[0] =   DOSTimeFromCalendar(curtime);
  201.               tempbackup[0] = DOSTimeFromCalendar(curtime);
  202.  
  203.               code = NLMLink("SetFileInfo", target, 0x06, dir[0].attrib,
  204.                      tempcreate,
  205.                      tempaccess,
  206.                      tempdate,
  207.                      tempbackup,
  208.                      dir[0].uid);
  209.               if( code )
  210.                 printf("\nError setting attributes for file %s\n",target);
  211.               return;
  212.             }
  213.           if( defined(_DOS_) || defined(_DOS32_) || defined(_WINDOWS_) )
  214.             {
  215.               SetFileDateAndTime(target,curtime);
  216.               return;
  217.             }
  218.           if( defined(_NTCON_) || defined(_NTWIN_) || defined(_95CON_) ||
  219.               defined(_95WIN_) )
  220.             {
  221.               newbuf = ""; SetArraySpan(newbuf,100);
  222.  
  223.               if( (handle = DynamicLink("KERNEL32","CreateFileA",STDCALL,target,
  224.                                GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
  225.                                NULL,OPEN_EXISTING,0,NULL))
  226.                  !=INVALID_HANDLE_VALUE)
  227.                 {
  228.                   dos = GMDOSTimeStructFromCalendar(time());
  229.                   if( !DynamicLink("KERNEL32","DosDateTimeToFileTime",STDCALL,
  230.                                    dos.date,dos.time,newbuf) )
  231.                     {
  232.                       printf("Unable to convert to NT Time structure.\n");
  233.                       return;
  234.                     }
  235.  
  236.                   if( !DynamicLink("KERNEL32","SetFileTime",STDCALL,handle,newbuf,
  237.                                    newbuf,newbuf) )
  238.                     {
  239.                       err = DynamicLink("KERNEL32","GetLastError",STDCALL);
  240.                       printf("Unable to set new file time.\n",err);
  241.                     }
  242.  
  243.                   if( !DynamicLink("KERNEL32","CloseHandle",STDCALL,handle) )
  244.                     printf("Unable to close the handle.\n");
  245.                 } else {
  246.                   printf("Unable to open the file to touch it.\n");
  247.                 }
  248.               return;
  249.             }
  250.  
  251.           if( defined(_OS2_) )
  252.             {
  253.               printf("Cannot set timestamps on OS/2 yet.\n");
  254.               return;
  255.             }
  256.         }
  257.       printf("Cannot copy file to itself.\n");
  258.       return;
  259.     }
  260.  
  261.  
  262.   if( (fp = fopen(source,stricmp(source,"con")?"rb":"rt"))==NULL )
  263.     {
  264.       printf("Unable to open source file %s\n",source);
  265.       return;
  266.     }
  267.   if( (fp2 = fopen(target,stricmp(target,"con")?"wb":"rt"))==NULL )
  268.     {
  269.       printf("Unable to open target file %s\n",target);
  270.       fclose(fp);
  271.       return;
  272.     }
  273.  
  274.   buffer = ""; SetArraySpan(buffer,10000);
  275.  
  276.   while( 1 )
  277.     {
  278.       num = fread(buffer,9900,fp);
  279.       if( num<1 ) break;
  280.       fwrite(buffer,num,fp2);
  281.     }
  282.  
  283.   fclose(fp2);
  284.   fclose(fp);
  285.  
  286.   if( verify )
  287.     {
  288.       if( !stricmp(target,"con") || !stricmp(source,"con") )
  289.         {
  290.           printf("Cannot verify to or from the console.\n");
  291.           return;
  292.         }
  293.       if( (fp = fopen(source,"rb"))==NULL )
  294.         {
  295.           printf("Unable to open source file %s\n",source);
  296.           return;
  297.         }
  298.       if( (fp2 = fopen(target,"rb"))==NULL )
  299.         {
  300.           printf("Unable to write target file %s; check path is correct\n",target);
  301.           fclose(fp);
  302.           return;
  303.         }
  304.  
  305.       buffer2 = ""; SetArraySpan(buffer2,10000);
  306.  
  307.       while( 1 )
  308.         {
  309.           num = fread(buffer,9900,fp);
  310.           if( num<1 ) break;
  311.           num2 = fread(buffer2,9900,fp2);
  312.           if( num!=num2 || memcmp(buffer,buffer2,num) )
  313.             {
  314.               printf("File \"%s\" was copied incorrectly.\n",target);
  315.             }
  316.         }
  317.  
  318.       fclose(fp2);
  319.       fclose(fp);
  320.     }
  321.  
  322.   if( !update_time && stricmp(target,"con") )
  323.     {
  324.       dir = Directory(source);
  325.       if( dir==NULL || GetArraySpan(dir)!=0 )
  326.         {
  327.           printf("Error, can no longer open source file!\n");
  328.           return;
  329.         }
  330.  
  331.       if( defined(_NWNLM_) )
  332.         {
  333.           tempcreate[0] = DOSTimeFromCalendar(dir[0].Create);
  334.           tempaccess[0] = DOSTimeFromCalendar(dir[0].Access);
  335.           tempdate[0] =   DOSTimeFromCalendar(dir[0].Write);
  336.           tempbackup[0] = DOSTimeFromCalendar(dir[0].Backup);
  337.  
  338.           code = NLMLink("SetFileInfo",
  339.                      target,
  340.                      0x06,
  341.                      dir[0].attrib,
  342.                      tempcreate,
  343.                      tempaccess,
  344.                      tempdate,
  345.                      tempbackup,
  346.                      dir[0].uid);
  347.           if( code )
  348.             printf("\nError setting attributes for file %s\n",target);
  349.         }
  350.       if( defined(_DOS_) || defined(_DOS32_) || defined(_WINDOWS_) )
  351.         {
  352.           SetFileDateAndTime(target,dir[0].Create);
  353.           SetFileAttributes(target,dir[0].attrib);
  354.         }
  355.       if( defined(_NTCON_) || defined(_NTWIN_) || defined(_95CON) ||
  356.           defined(_95WIN_) )
  357.         {
  358.           DynamicLink("KERNEL32","SetFileAttributesA",STDCALL,target,dir[0].attrib);
  359.  
  360.           FTimeDef.LowTime = UWORD32;
  361.           FTimeDef.HightTime = UWORD32;
  362.  
  363.           if( (handle = DynamicLink("KERNEL32","CreateFileA",STDCALL,target,
  364.                                     GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
  365.                                     NULL,OPEN_EXISTING,0,NULL))
  366.              !=INVALID_HANDLE_VALUE)
  367.             {
  368.               dos = GMDOSTimeStructFromCalendar(dir[0].Create);
  369.               DynamicLink("KERNEL32","DosDateTimeToFileTime",STDCALL,
  370.                           dos.date,dos.time,FTimeDef,CreateFTime);
  371.               dos = GMDOSTimeStructFromCalendar(dir[0].Access);
  372.               DynamicLink("KERNEL32","DosDateTimeToFileTime",STDCALL,
  373.                           dos.date,dos.time,FTimeDef,AccessFTime);
  374.               dos = GMDOSTimeStructFromCalendar(dir[0].Write);
  375.               DynamicLink("KERNEL32","DosDateTimeToFileTime",STDCALL,
  376.                           dos.date,dos.time,FTimeDef,WriteFTime);
  377.  
  378.               if( !DynamicLink("KERNEL32","SetFileTime",STDCALL,handle,FTimeDef,CreateFTime,
  379.                                FTimeDef,AccessFTime,FTimeDef,WriteFTime) )
  380.                 {
  381.                   err = DynamicLink("KERNEL32","GetLastError",STDCALL);
  382.                   printf("Unable to set new file time.\n",err);
  383.                 }
  384.  
  385.                   if( !DynamicLink("KERNEL32","CloseHandle",STDCALL,handle) )
  386.                     printf("Unable to close the handle.\n");
  387.                 } else {
  388.                   printf("Unable to open the file to touch it.\n");
  389.                 }
  390.               return;
  391.         }
  392.  
  393.       if( defined(_OS2_) )
  394.         {
  395.           printf("Cannot set time on OS/2 yet.\n");
  396.           exit(EXIT_FAILURE);
  397.         }
  398.     }
  399. }
  400.  
  401. copy_multiple(target)
  402. {
  403.   if( (fp2 = fopen(target,"w"))==NULL )
  404.     {
  405.       printf("Unable to write target file %s; check path is correct.\n",target);
  406.       return;
  407.     }
  408.  
  409.   buffer = ""; SetArraySpan(buffer,1024);
  410.   for( i=0;i<num_source;i++ )
  411.     {
  412.       files = Directory(source[i]);
  413.       for( j=0;files && j<=GetArraySpan(files);j++ )
  414.         {
  415.           if( (fp = fopen(files[j].name,"r"))==NULL )
  416.             {
  417.               printf("Unable to open source file %s\n",source);
  418.               fclose(fp2);
  419.               return;
  420.             }
  421.           do
  422.             {
  423.               num = fread(buffer,1024,fp);
  424.               if( num<1 ) break;
  425.               fwrite(buffer,num,fp2);
  426.             }
  427.           while( !feof(fp) );
  428.           fclose(fp);
  429.         }
  430.     }
  431.  
  432.   fclose(fp2);
  433. }
  434.  
  435. /*---------------------------------------------------------------------------*/
  436.  
  437. get_filename(source)
  438. {
  439.   filestruct = SplitFileName(source);
  440.   sprintf(newdir,"%s%s",filestruct.name,filestruct.ext);
  441.   return newdir;
  442. }
  443.  
  444.  
  445. main(argc,argv)
  446. {
  447.   if( defined(_OS2_) )
  448.     {
  449.       printf("This script does not yet support OS/2.\n");
  450.       exit(EXIT_FAILURE);
  451.     }
  452.  
  453.   parse_command_line(argc,argv);
  454.  
  455.   tar_dir = 0;
  456.   must_dir = 0;
  457.   s = strlen(target);
  458.   if( target[s-1]==filename_separator[0] )
  459.     {
  460.       target[s-1] = '\0';
  461.       must_dir = 1;
  462.     }
  463.  
  464.   if( !strcmp(target,".") )
  465.     {
  466.       strcat(target,filename_separator);
  467.       tarfiles = NULL;
  468.     } else tarfiles = Directory(target);
  469.  
  470.   if( tarfiles==NULL )
  471.     {
  472.       if( !strcmp(target,".\\") ) tar_dir = 1;
  473.       if( isalpha(target[0]) && target[1]==':' &&
  474.          (target[2]=='\0' ||
  475.           ((target[2]=='/' || target[2]=='\\') && target[3]=='\0') ) )
  476.         tar_dir = 1;
  477.     } else {
  478.       if( GetArraySpan(tarfiles)>0 )
  479.         {
  480. // This is the case where the user typed something like : copy *.txt *.bak
  481.           printf("Cannot copy file(s) to multiple destinations.\n");
  482.           exit(EXIT_FAILURE);
  483.         }
  484.       strcpy(target,tarfiles[0].name);
  485.       if( tarfiles[0].attrib & _A_SUBDIR )
  486.         {
  487.           tar_dir = 1;
  488.           strcat(target,"\\");
  489.         }
  490.     }
  491.  
  492.   if( must_dir && !tar_dir )
  493.     {
  494.       printf("Destination specified as a directory but is actually a file.\n");
  495.       exit(EXIT_FAILURE);
  496.     }
  497.  
  498.   if( num_source==1 )
  499.     {
  500.       files = Directory(source[0]);
  501.       if( files==NULL )
  502.         {
  503.           printf("No such file or directory.\n");
  504.           exit(EXIT_FAILURE);
  505.         }
  506. // If multiple file move, the target must be a directory, otherwise just copy
  507. // the old file to the new one.
  508.       if( GetArraySpan(files)>0 )
  509.         {
  510.           if( !tar_dir )
  511.             {
  512.               copy_multiple(target); exit(EXIT_SUCCESS);
  513.             }
  514.  
  515.           for( i=0;i<=GetArraySpan(files);i++ )
  516.             {
  517.               if( (files[i].attrib & _A_SUBDIR)==0 )
  518.                 {
  519.                   strcpy(tmp,target);
  520.                   strcat(tmp,get_filename(files[i].name));
  521.                   copy_file(files[i].name,tmp);
  522.                 }
  523.             }
  524.         } else {
  525.           if( tar_dir )
  526.             {
  527.               sprintf(tmp,"%s%s",target,get_filename(files[0].name));
  528.             } else {
  529.               strcpy(tmp,target);
  530.             }
  531.           copy_file(files[0].name,tmp);
  532.         }
  533.     } else {
  534. // In this case, we copy multiple files into a single file, concatenating them
  535.       if( tar_dir )
  536.         {
  537.           sprintf(tmp,"%s%s",target,get_filename(files[0].name));
  538.         } else {
  539.           strcpy(tmp,target);
  540.         }
  541.       copy_multiple(tmp);
  542.     }
  543. }
  544.