home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / cenvi23.zip / XCOPY.CMM < prev    next >
Text File  |  1996-01-29  |  14KB  |  446 lines

  1. /*
  2.  * XCopy.cmm
  3.  *
  4.  * An xcopy script for the CEnvi shell. It does what the DOS xcopy
  5.  * command does.
  6.  */
  7.  
  8. #include "netware.lib"
  9.  
  10. usage()
  11. {
  12.   printf("Use the XCOPY command to selectively copy groups of files.\n");
  13.   printf("Syntax:\n");
  14.   printf("  XCOPY [drive:][path] filename [drive:][path] filename [/S][/E]\n");
  15.   printf("        [/A][/M][/H][/T][/R][/O]\n");
  16.   printf("where:\n");
  17.   printf("  drive:/path/filename  Specifies the location of the file to copy.\n");
  18.   printf("  drive:/path/filename  Specified the target destination and file name.\n");
  19.   printf("  /S                    Copies non-empty directories and subdirectories.\n");
  20.   printf("  /E                    When used with /S, copies entire tree structure,\n");
  21.   printf("                        including subdirectories even if they are empty.\n");
  22.   printf("  /A                    Copies archived files only, but does not turn\n");
  23.   printf("                        off the attribute bit of the source file.\n");
  24.   printf("  /M                    Copies archived files only and turns off the\n");
  25.   printf("                        attribute bit of the source file.\n");
  26.   printf("  /H                    Allows hidden files to be copied to the\n");
  27.   printf("                        destination and retain their hidden attribute.\n");
  28.   printf("  /T                    Allows system files to be copied to the\n");
  29.   printf("                        destination and retain their system attribute.\n");
  30.   printf("  /R                    Allows read-only files to be copied to the\n");
  31.   printf("                        destination and retain the read-only attribute,\n");
  32.   printf("  /O                    Specifies that any read-only, hidden, or system\n");
  33.   printf("                        files in the destination can be overwritten by\n");
  34.   printf("                        the copy operation.\n");
  35.   exit(EXIT_FAILURE);
  36. }
  37.  
  38. /*---------------------------------------------------------------------------*/
  39.  
  40. recursive = FALSE;
  41. empty = FALSE;
  42. archived_only = FALSE;
  43. turn_off_archived = FALSE;
  44. copy_hidden = FALSE;
  45. copy_system = FALSE;
  46. copy_readonly = FALSE;
  47. overwrite = FALSE;
  48. source = "";
  49. target = "";
  50.  
  51.  
  52. parse_command_line(argc,argv)
  53. {
  54.   for( i=1;i<argc;i++ )
  55.     {
  56.       if( argv[i][0]=='-' || argv[i][0]=='/' )
  57.         {
  58.           switch( toupper(argv[i][1]) )
  59.             {
  60.             default: usage(); exit(1);
  61.             case 'S': recursive = TRUE; break;
  62.             case 'E': empty = TRUE;
  63.             case 'M': turn_off_archived = TRUE; // intentional fall-thru
  64.             case 'A': archived_only = TRUE; break;
  65.             case 'H': copy_hidden = TRUE; break;
  66.             case 'T': copy_system = TRUE; break;
  67.             case 'R': copy_readonly = TRUE; break;
  68.             case 'O': overwrite = TRUE; break;
  69.             }
  70.           continue;
  71.         }
  72. // Else here we have a filename
  73.       if( source[0]=='\0' )
  74.         {
  75.           strcpy(source,argv[i]);
  76.           continue;
  77.         }
  78.       if( target[0]=='\0' )
  79.         {
  80.           strcpy(target,argv[i]);
  81.           continue;
  82.         }
  83.       printf("You may not specify more than one source or target.\n");
  84.       exit(1);
  85.     }
  86.   if( source[0]=='\0' )
  87.     {
  88.       printf("No source file specified.\n");
  89.       exit(1);
  90.     }
  91.   if( target[0]=='\0' )
  92.     {
  93.       printf("No target directory specified.\n");
  94.       exit(1);
  95.     }
  96. }
  97.  
  98. /*---------------------------------------------------------------------------*/
  99.  
  100. unprotect(file)
  101. {
  102.   if( defined(_NWNLM_) )
  103.     {
  104.       temp[0] = DOSTimeFromCalendar(time());
  105.       
  106.       code = NLMLink("SetFileInfo",
  107.                      file.name,
  108.                      0x06,
  109.                      file.attrib & ~(_A_RDONLY|_A_SYSTEM|_A_HIDDEN),
  110.                      tempcreate,
  111.                      tempaccess,
  112.                      tempdate,
  113.                      tempbackup,
  114.                      file.uid);
  115.       if( code )
  116.         printf("\nError setting attributes for file %s\n",file.name);
  117.       return;
  118.     }
  119.   if( defined(_DOS_) || defined(_DOS32_) || defined(_WINDOWS_) )
  120.     {
  121.       SetFileAttributes(file.name,file.attrib & ~_A_RDONLY);
  122.       return;
  123.     }
  124.   if( defined(_NTCON_) || defined(_NTWIN_) || defined(_95CON_) ||
  125.       defined(_95WIN_) )
  126.     {
  127.       DynamicLink("KERNEL32","SetFileAttributesA",STDCALL,file.name,
  128.                   file.attrib & ~_A_RDONLY);
  129.       return;
  130.     }
  131.   if( defined(_OS2_) )
  132.     {
  133.     }
  134. }
  135.  
  136. DOSTimeFromCalendar(time)
  137. {
  138.   dos = DOSTimeStructFromCalendar(time);
  139.   return dos.time<<16 | dos.date;
  140. }
  141.  
  142. DOSTimeStructFromCalendar(time)
  143. {
  144.   tm = localtime(time);
  145.   dos.time = (tm.tm_sec/2) | (tm.tm_min<<5) | (tm.tm_hour<<11);
  146.   dos.date = tm.tm_mday | ((tm.tm_mon+1)<<5) | ((tm.tm_year-80)<<9);
  147.   return dos;
  148. }
  149.  
  150. GMDOSTimeStructFromCalendar(time)
  151. {
  152.   tm = gmtime(time);
  153.   dos.time = (tm.tm_sec/2) | (tm.tm_min<<5) | (tm.tm_hour<<11);
  154.   dos.date = tm.tm_mday | ((tm.tm_mon+1)<<5) | ((tm.tm_year-80)<<9);
  155.   return dos;
  156. }
  157.  
  158.  
  159. /*
  160.  * Some DOS functions
  161.  */
  162. SetFileAttributes(pFileName,pAttributes)
  163. {
  164.    lReg.ah = 0x43;
  165.    lReg.al = 1;
  166.    lReg.cx = pAttributes;
  167.    if !defined(_DOS32_)
  168.       lReg.ds = segment(pFileName), lReg.dx = offset(pFileName);
  169.    else
  170.       lReg.dx = pointer(pFileName);
  171.    return interrupt(0x21,lReg);
  172. }
  173.  
  174. SetFileDateAndTime(pFileName,pTime)
  175. {
  176.    lSuccess = False;
  177.    // Open file to get a handle
  178.    lReg.ah = 0x3D;
  179.    lReg.al = 0x42;
  180.    if !defined(_DOS32_)
  181.       lReg.ds = segment(pFileName), lReg.dx = offset(pFileName);
  182.    else
  183.       lReg.dx = pointer(pFileName);
  184.    if ( interrupt(0x21,lReg,lRegout) ) {
  185.       lHandle = lRegout.ax;
  186.       // write date to file
  187.       undefine(lReg);
  188.       lReg.ah = 0x57;
  189.       lReg.al = 1;
  190.       lReg.bx = lHandle;
  191.       lTm = localtime(pTime);
  192.       lReg.cx = (lTm.tm_sec / 2)
  193.               | (lTm.tm_min << 5)
  194.               | (lTm.tm_hour << 11);
  195.       lReg.dx = lTm.tm_mday
  196.               | ((lTm.tm_mon+1) << 5)
  197.               | ((lTm.tm_year-80) << 9);
  198.       lSuccess = interrupt(0x21,lReg);
  199.       // close file
  200.       undefine(lReg);
  201.       lReg.ah = 0x3E;
  202.       lReg.bx = lHandle;
  203.       interrupt(0x21,lReg);
  204.    }
  205.    return lSuccess;
  206. }
  207.  
  208. #define GENERIC_WRITE 0x40000000
  209. #define FILE_SHARE_READ 0x01
  210. #define FILE_SHARE_WRITE 0x02
  211. #define OPEN_EXISTING 3
  212. #define INVALID_HANDLE_VALUE -1
  213.  
  214. mymkdir(pDirName) // no return value
  215. {
  216.    if defined(_OS2_) {
  217.       #define ORD_DOS32CREATEDIR 270
  218.       return !DynamicLink("doscalls",ORD_DOS32CREATEDIR,BIT32,CDECL,pDirName,0)
  219.    } else if ( defined(_NTCON_) || defined(_NTWIN_) || defined(_95CON_) ||
  220.                defined(_95WIN_) ) {
  221.       return !DynamicLink("KERNEL32","CreateDirectoryA",STDCALL,pDirName,NULL);
  222.    } else if( defined(_NWNLM_) )
  223.    {
  224.      return mkdir(pDirName);
  225.    } else { // dos or windows use the same code
  226.     lReg.ah = 0x39;
  227.     if !defined(_DOS32_)
  228.        lReg.ds = segment(pDirName), lREg.dx = offset(pDirName);
  229.     else
  230.        lReg.dx = pointer(pDirName);
  231.     return !interrupt(0x21,lReg);
  232.    }
  233. }
  234.  
  235. /* ---------------------------------------------------------------------- */
  236.  
  237. /*
  238.  * Copy a single file. When done, set the time to the old file's time stamp.
  239.  */
  240. copy_file(target,source)
  241. {
  242.   if( (fp = fopen(source,"rb"))==NULL )
  243.     {
  244.       printf("Unable to open source file %s\n",source);
  245.       return;
  246.     }
  247.   if( (fp2 = fopen(target,"wb"))==NULL )
  248.     {
  249.       unprotect(Directory(target)[0],0x3f);
  250.       if( (fp2 = fopen(target,"wb"))==NULL )
  251.         {
  252.           printf("Unable to open target file %s\n",target);
  253.           fclose(fp);
  254.           return;
  255.         }
  256.     }
  257.  
  258.   buffer = ""; SetArraySpan(buffer,1024);
  259.  
  260.   while( 1 )
  261.     {
  262.       num = fread(buffer,1024,fp);
  263.       if( num<1 ) break;
  264.       fwrite(buffer,num,fp2);
  265.     }
  266.  
  267.   fclose(fp2);
  268.   fclose(fp);
  269.  
  270.   dir = Directory(source);
  271.   if( dir==NULL || GetArraySpan(dir)!=0 )
  272.     {
  273.       printf("Error, can no longer open source file!\n");
  274.       return;
  275.     }
  276.  
  277.   new_attrib = dir[0].attrib;
  278. // By default, we copy the files and mark them as archived.
  279.   new_attrib |= _A_ARCH;
  280.   if( turn_off_archived ) new_attrib &= ~_A_ARCH;
  281.   if( !copy_readonly ) new_attrib &= ~_A_RDONLY;
  282.  
  283.   if( defined(_NWNLM_) )
  284.     {
  285.       tempcreate[0] = DOSTimeFromCalendar(dir[0].Create);
  286.       tempaccess[0] = DOSTimeFromCalendar(dir[0].Access);
  287.       tempdate[0] =   DOSTimeFromCalendar(dir[0].Write);
  288.       tempbackup[0] = DOSTimeFromCalendar(dir[0].Backup);
  289.  
  290.       code = NLMLink("SetFileInfo",
  291.                  target,
  292.                  0x06,
  293.                  new_attrib,
  294.                  tempcreate,
  295.                  tempaccess,
  296.                  tempdate,
  297.                  tempbackup,
  298.                  dir[0].uid);
  299.  
  300.       if( code )
  301.         printf("\nError setting attributes for file %s\n",target);
  302.       return;
  303.     }
  304.   if( defined(_DOS_) || defined(_DOS32_) || defined(_WINDOWS_) )
  305.     {
  306.       SetFileDateAndTime(target,dir[0].Create);
  307.       SetFileAttributes(target,new_attrib);
  308.       return;
  309.     }
  310.   if( defined(_NTCON_) || defined(_NTWIN_) || defined(_95CON_) ||
  311.       defined(_95WIN_) )
  312.     {
  313.       createbuf = ""; SetArraySpan(createbuf,4);
  314.       accessbuf = ""; SetArraySpan(accessbuf,4);
  315.       writebuf = ""; SetArraySpan(writebuf,4);
  316.  
  317.       if( (handle = DynamicLink("KERNEL32","CreateFileA",STDCALL,target,
  318.                                 GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
  319.                                 NULL,OPEN_EXISTING,0,NULL))
  320.          !=INVALID_HANDLE_VALUE)
  321.         {
  322.           dos = GMDOSTimeStructFromCalendar(dir[0].Create);
  323.           DynamicLink("KERNEL32","DosDateTimeToFileTime",STDCALL,
  324.                       dos.date,dos.time,createbuf);
  325.           dos = GMDOSTimeStructFromCalendar(dir[0].Access);
  326.           DynamicLink("KERNEL32","DosDateTimeToFileTime",STDCALL,
  327.                       dos.date,dos.time,accessbuf);
  328.           dos = GMDOSTimeStructFromCalendar(dir[0].Write);
  329.           DynamicLink("KERNEL32","DosDateTimeToFileTime",STDCALL,
  330.                       dos.date,dos.time,writebuf);
  331.  
  332.           if( !DynamicLink("KERNEL32","SetFileTime",STDCALL,handle,createbuf,
  333.                            accessbuf,writebuf) )
  334.             {
  335.               err = DynamicLink("KERNEL32","GetLastError",STDCALL);
  336.               printf("Unable to set new file time.\n",err);
  337.             }
  338.  
  339.           if( !DynamicLink("KERNEL32","CloseHandle",STDCALL,handle) )
  340.             printf("Unable to close the handle.\n");
  341.         } else {
  342.           printf("Unable to open file %s to touch it.\n",target);
  343.         }
  344.  
  345. // Set the file's attributes second, so we don't turn back on read-only,
  346. // then try to set file attributes.
  347.       DynamicLink("KERNEL32","SetFileAttributesA",STDCALL,target,new_attrib);
  348.       return;
  349.     }
  350.  
  351.   if( defined(_OS2_) )
  352.     {
  353.       printf("I do not know how to set file attributes on this system.\n");
  354.       exit(EXIT_FAILURE);
  355.     }
  356. }
  357.  
  358. /* --------------------------------------------------------------------------- */
  359.  
  360. get_filename(source)
  361. {
  362.   filestruct = SplitFileName(source);
  363.   sprintf(newdir,"%s%s",filestruct.name,filestruct.ext);
  364.   return newdir;
  365. }
  366.  
  367.  
  368. /*
  369.  * Copy all files from the src directory to the tar directory. Silently create
  370.  * the target directory if it does not already exist. Use the global flags
  371.  * to determine whether to do subdirectories and what to do about special files.
  372.  */
  373. copy_dir(tar,src)
  374. {
  375.   printf("Copying directory %s...\n",FullPath(src));
  376.   may_have = 0x3f;
  377.   if( !copy_hidden ) may_have &= ~_A_HIDDEN;
  378.   if( !copy_system ) may_have &= ~_A_SYSTEM;
  379.   if( defined(_NWNLM_) ) may_have |= _A_NORENAM | _A_NODELET;
  380.   must_have = archived_only?_A_ARCH:0;
  381.  
  382.   strcpy(srcfiles,src);
  383.   if( defined(_NWNLM_) )
  384.     strcat(srcfiles,"/*.*");
  385.   else
  386.     strcat(srcfiles,"\\*.*");
  387.  
  388.   files = Directory(srcfiles,FALSE,may_have,must_have);
  389.   if( files==NULL && !empty ) return;
  390.  
  391.   mymkdir(tar);
  392.  
  393.   if( files==NULL ) return;
  394.   for( i=0;i<=GetArraySpan(files);i++ )
  395.     {
  396.       if( files[i].attrib & _A_SUBDIR )
  397.         {
  398.           if( recursive )
  399.             {
  400.               strcpy(newname,tar);
  401.               if( newname[strlen(newname)-1]!='/' && newname[strlen(newname)-1]!='\\' )
  402.                 {
  403.                   if( defined(_NWNLM_) )
  404.                     strcat(newname,"/");
  405.                   else
  406.                     strcat(newname,"\\");
  407.                 }
  408.               strcat(newname,get_filename(files[i].name));
  409.               copy_dir(newname,files[i].name);
  410.             }
  411.         } else {
  412.           strcpy(newname,tar);
  413.           if( newname[strlen(newname)-1]!='/' && newname[strlen(newname)-1]!='\\' )
  414.             {
  415.               if( defined(_NWNLM_) )
  416.                 strcat(newname,"/");
  417.               else
  418.                 strcat(newname,"\\");
  419.             }
  420.           strcat(newname,get_filename(files[i].name));
  421.           copy_file(newname,files[i].name);
  422.         }
  423.     }
  424. }
  425.  
  426. /* --------------------------------------------------------------------------- */
  427.  
  428. main(argc,argv)
  429. {
  430.   parse_command_line(argc,argv);
  431.  
  432.   tar = Directory(target);
  433.   if( tar==NULL )
  434.     {
  435.       printf("The target does not exist. Assuming you wish to make a new directory\n");
  436.       printf("with that name...\n\n");
  437.       if( mymkdir(target) )
  438.         {
  439.           printf("Unable to make the specified directory.\n");
  440.           exit(1);
  441.         }
  442.     }
  443.     
  444.   copy_dir(target,source);
  445. }
  446.