home *** CD-ROM | disk | FTP | other *** search
/ Falcon 030 Power 2 / F030_POWER2.iso / ST_STE / MAGS / ICTARI03.ARJ / ictari.03 / C / BACKUP / BACKUP.C next >
C/C++ Source or Header  |  1987-04-22  |  23KB  |  724 lines

  1. /***********************************************************************/
  2. /*                                                                     */
  3. /*                                                                     */
  4. /***********************************************************************/
  5. /*                           INCLUDE FILES                             */
  6. /***********************************************************************/
  7.  
  8. #include <portab.h>                             /* portable coding conv */
  9. #include <machine.h>                            /* machine depndnt conv */
  10. #include <obdefs.h>                             /* object definitions   */
  11. #include <treeaddr.h>                           /* tree address macros  */
  12. #include <gembind.h>                            /* gem binding structs  */
  13. #include <tosdefs.h>
  14. #include <osbind.h>
  15. #include "backup.h"
  16.  
  17. /***********************************************************************/
  18. /*                            DEFINES                                  */
  19. /***********************************************************************/
  20.  
  21. #define FILENM    "TIMESTMP.HD"        /* Timestamp File ID    */
  22.  
  23. #define window_kind (NAME|CLOSER)
  24.  
  25. #define SFILE_ATTR 0x07        /* Look for files */
  26. #define SFILE_DIR  0x10        /* Directory File attribute    */
  27.  
  28. #define ARROW           0
  29. #define HOUR_GLASS      2
  30.  
  31. #define END_UPDATE      0
  32. #define BEG_UPDATE      1
  33.  
  34. /***********************************************************************/
  35. /*                        GLOBAL VARIABLES                             */
  36. /***********************************************************************/
  37.  
  38. /* Disk Transfer Address (DTA) structure */
  39. struct disk_buf
  40.    {
  41.    char system[21];     /* first 21 bytes reserved for system    */
  42.    char attr;           /* file attribute */
  43.    int  ftime;          /* file time stamp */
  44.    int  fdate;          /* file date stamp */
  45.    long fsize;          /* file size in bytes */
  46.    char fname[14];      /* file name and extension */
  47.    };
  48.  
  49. struct disk_buf dtabuf; /* Dta buffer                 */
  50. struct disk_buf dta1buf;/* Dta buffer 1                */
  51. struct disk_buf *dta;     /* pointer 'dta' will point to structure */
  52. struct disk_buf *dta1;     /* pointer 'dta' will point to structure */
  53.  
  54. long sysdta;    /* Save System DTA address    */
  55.  
  56. int wi_handle, ap_id, phys_handle, ph, intin[128],work_in[11],h,w,hh,ww;
  57. int contrl[12],ptsin[128],intout[128],ptsout[128],work_out[60];
  58. int xdesk, ydesk, wdesk, hdesk, dum, clip[4];
  59. long tree;
  60. int mausx, mausy, dummy;
  61. int xwork, ywork, wwork, hwork;
  62.  
  63. int type_update = FILE;    /* Type of update entered; time, timestamp, or All */
  64. int  autowrite = TRUE;    /* FALSE = query for file overwrite    */
  65. char src[]  = "C:";    /* Source Drive                */
  66. char dest[] = "A:";    /* Destination Drive            */
  67. int  isrc  = 3;        /* Source drive use A             */
  68. int  idest = 1;        /* Destination Drive use 'M'        */
  69.  
  70. OBJECT *obj;        /* OBJECT Structure - map into resource file    */
  71. TEDINFO *ted;        /* TED Structure - map into resource file    */
  72.  
  73. int res;        /* Screen Res                */
  74. int date_backup[2];    /* Hold backup file date/time        */
  75. char dir[255];        /* Hold Directory search path        */
  76. char dta_sav[255];    /* recursive save 1st 21 bytes of dta between calls */
  77. char *icp, *ocp;    /* Temp pointers global because of recursive call */
  78. int cnt;        /*   "     "        "      "    "      "       "  */
  79.  
  80. long  dsk_blk[4];    /* Free Alloc Units|Total|Bytes/Sect|Phys Sect/Alloc */
  81. /***********************************************************************/
  82. /*                            ALERT BOXES                              */
  83. /***********************************************************************/
  84.  
  85. char alert1[] = "[1][XXXXXXXXXXXXXXXXXXXX| TED String Found!][Cont]";
  86. char alert4[] = "[1][XXXXXXXX.XXX found|To be Backed UP!][Cont]";
  87. char alert5[] = "[1][XXXXXXXX.XXX found|Processing Directory!][Cont]";
  88. char alert6[] = "[1][XXXXXXXXXXXXXXXXXXXX|Processing Directory!|(find_file)][Cont]";
  89. char alert8[] = "[3][XXXXXXXXXXXXXXXXXXXX|Error Opening|Input file!][Cont]";
  90. char alert9[] = "[3][XXXXXXXXXXXXXXXXXXXX|Error Opening|Output File!][Cont]";
  91. char alerta[] = "[3][XXXXXXXXXXXXXXXXXXXX|  Bad Create | Directory! ][Cont]";
  92. char alertb[] = "[1][XXXXXXXXXXXXXXXXXXXX|  Making | Directory! ][Cont]";
  93. char alertc[] = "[3][XXXXXXXXXXXXXXXXXXXX|  Bad | Change Drive! ][Cont]";
  94. char alertd[] = "[3][XXXXXXXXXXXXXXXXXXXX| On Destination Drive | Overwrite File? ][ YES | NO ]";
  95. char alertf[] = "[3][XXXXXXXXXXXXXXXXXXXX| Not All of File | Copied! ][Cont]";
  96. char alertg[] = "[3][XXXXXXXXXXXXXXXXXXXX| File Write Error! ][Cont]";
  97. char alerth[] = "[1][XXXXXXXXXXXXXXXXXXXX| Checking for | Directory! ][Cont]";
  98. char alertj[] = "[3][ Problem | Creating | OR | Deleting | TIMESTMP.HD! ][Cont ]";
  99. char alertx[] = "[3][XXXXXXXXXXXXXXXXXXXX| Exists as file. Cannot | Create Directory. | Please Insert | Another Diskette! ][Cont]";
  100.  
  101. /***********************************************************************/
  102. /***********************************************************************/
  103. /*                                                                     */
  104. /*                          PROGRAM CONTROL                            */
  105. /*                                                                     */
  106. /***********************************************************************/
  107. /***********************************************************************/
  108. main()
  109. {
  110. WORD    term_type;
  111.  
  112. if ( !(term_type = pgm_init()) )
  113.     if ( ask_scn() == 0 )
  114.         if ( get_parms() == 0 ) {
  115.             if ( type_update == DATE ) {
  116.         if ( opt_date() == 0 )
  117.             file_backup();
  118.         }
  119.         else
  120.             file_backup();     
  121.         }
  122. pgm_term(term_type);
  123. }
  124.  
  125. file_backup()    /* Main Processing - find, check, and backup files */
  126. {
  127.     
  128. int ret;
  129.  
  130. dta  = &dtabuf;         /* pointer 'dta' will point to structure */
  131. dta1 = &dta1buf;        /*         X             */
  132. Fsetdta(dta);        /* Set DTA buffer            */
  133. strcpy(dir, src);
  134. do_dir(dta_sav);           /*start the backup */
  135. if ( (ret = form_alert(1, "[2][ Backup Completed | Create / Update | TIMESTMP.HD? ][ YES | NO ]")) == 1 )
  136.     updat_ts();        /* Update timestamp file    */        
  137.  
  138. }
  139.          
  140. do_dir(dtasv)
  141. char *dtasv;        /* Start of dta save area (1st 21 bytes)    */
  142.  
  143. /***************************************************************************
  144.  
  145.         Find Files That needs to be backed up
  146.         
  147. ****************************************************************************/
  148.  
  149. {
  150. int  status;    
  151. long dirlen;        /* Length of path up to this point (+1)    */
  152.  
  153. dirlen = strlen(dir) + 1;    /* Save length of pathname to this point */
  154. strcat(dir, "\\*.*");   /* Start with 1st file        */
  155. //cpynchar(alert6 + 4L, dir, 20);
  156. //form_alert(1,alert6);
  157.  
  158. status = Fsfirst(dir, SFILE_ATTR); 
  159. while ( status == E_OK ) {    /* Do for all files first    */
  160.     if ( cmp_datime(&dta->ftime) ) {
  161. //        cpynchar(alert4 + 4L, dta->fname, 12);    
  162. //        form_alert(1,alert4);
  163.         LBCOPY(dta1, dta, 44);
  164.         do {    /* Until Space & all required subdirectories are present */
  165.             check_dest();
  166.             status = make_dir(dirlen); /* Make any needed dirs */
  167.             }
  168.         while ( status != 0 );
  169.         LBCOPY(&dta->attr, &dta1->attr, 23);
  170.         backup_file(dirlen);
  171.         LBCOPY(dta, dta1, 21);
  172.         }
  173.     status = Fsnext();    
  174.     }    
  175.  
  176. strcpy(dir + dirlen, "*.*");   /* Start with 1st Directory        */
  177. //cpynchar(alert6 + 4L, dir, 20);
  178. //form_alert(1,alert6);
  179.         
  180. status = Fsfirst(dir, SFILE_DIR); /* Start processing any Sub-Directories */
  181. while ( status == E_OK ) {
  182.     if ( dta->attr ==  (char)SFILE_DIR            &&
  183.          strncmp(dta->fname, ". ", 2)  != 0       &&
  184.          strncmp(dta->fname, ".. ", 3) != 0 ) {
  185. //        cpynchar(alert5 + 4L, dta->fname, 12);     
  186. //        form_alert(1,alert5);
  187.         strcpy(dir + dirlen, dta->fname);
  188.         LBCOPY(dtasv, dta->system, 21);
  189.         do_dir(dtasv + 21);        /* Recursive call for next dir */
  190.         LBCOPY(dta->system, dtasv, 21);
  191.         }
  192.     status = Fsnext();        
  193.     }
  194.  
  195. }
  196.  
  197. int make_dir(dirlen)
  198. long dirlen;     /* Length of Path up to this point    */
  199. /***************************************************************************
  200.  
  201.     Make any directories on target (if space exists for file)
  202.     
  203. ***************************************************************************/
  204. {
  205.  
  206. char  *ip, *ip1;    /* Temp char pointers    */
  207. int   ret;        /* System Return code    */
  208. int   retcd = 0;    /* Set return code to good     */
  209.  
  210. dir[0] = dest[0];    /* Correct filename to destination drive    */
  211.  
  212. for ( ip = dir + dirlen - 1L; *ip != '\\'; ip-- ) /* Get to last \    */
  213.     ;
  214. if ( ip > dir + 2L ) {    /* See if subdirectories    */    
  215.     ip1 = dir + 3L;
  216.     while ( 1 ) {     /* Do for every subdirectory    */
  217.     for ( ; *ip1 != '\\'; ip1++ ) /* Get to end of 1st dir */
  218.             ;
  219.         *ip1 = NULL;
  220. //        cpynchar(alerth + 4L, dir, 20);
  221. //        form_alert(1, alerth);
  222.         if ( (ret = Fsfirst(dir, 0x1f)) != 0 ) {
  223. //            cpynchar(alertb + 4L, dir, 20);
  224. //            form_alert(1, alertb);
  225.         if ( (retcd = Dcreate(dir)) != 0 ) {
  226.                 cpynchar(alerta + 4L, dir, 20);     
  227.                 form_alert(1, alerta);
  228.                 break;
  229.             }
  230.             }
  231.         else
  232.             if ( dta->attr != (char)SFILE_DIR ) {
  233.                 cpynchar(alertx +4L, dir, 20);
  234.                 form_alert(1,alertx);
  235.                 retcd = 1;
  236.                 break;
  237.                 }        
  238.         *(ip1++) = '\\';            
  239.         if ( ip1 > ip )
  240.             break;
  241.     }        
  242.     }    
  243.  
  244. dir[0] = dest[0];    /* Correct filename to destination drive    */
  245. return(retcd);
  246.  
  247. }
  248.  
  249. check_dest()    
  250. /***************************************************************************
  251.  
  252.           Check Destination For enought Space for File to Copy
  253.           
  254. ***************************************************************************/
  255. {      
  256.             /* Disk Block    */
  257. long  alloc_req;    /* Number of allocation units required for curr file */
  258.  
  259. while ( 1 ) {
  260.     Dfree(&dsk_blk, idest);    /* Get Free space from Destination Drive */
  261.     alloc_req =  ( dta1->fsize + (dsk_blk[2] * dsk_blk[3] - 1) )
  262.                / (dsk_blk[2] * dsk_blk[3]);
  263.     if ( alloc_req <= dsk_blk[0] )
  264.         break;
  265.     form_alert(1,
  266.              "[3][Not Enought Space on| Destination. Change Disk!][ OK ]");
  267.     }
  268. }
  269.     
  270. backup_file(dirlen)
  271. long dirlen;    /* Length of Path up to this point        */
  272.  
  273. /***************************************************************************
  274.  
  275.     Backup File that has been selected
  276.     
  277. ***************************************************************************/
  278. {
  279. int ret, handle;
  280. long ret2, sbyte;
  281. char *ptr;
  282.  
  283. strcpy(dir + dirlen, dta->fname);    /* Append file to path    */
  284.     
  285. dir[0] = dest[0];    /* Set drive to Destination    */              
  286. sbyte = dta->fsize;
  287.  
  288. if ((ret = Fsfirst(dir, 0x00)) == 0) {
  289.     cpynchar(alertd + 4L, dir, 20);    
  290.     if ( autowrite == TRUE      ||
  291.          (ret =form_alert(1, alertd)) == 1 ) {
  292.         if ( (ret2 = Fdelete(dir)) != 0 ) {
  293.             cpynchar(alert9 + 4L, dir, 20);      
  294.             form_alert(1, alert9);        
  295.             dir[0] = src[0];
  296.             return;
  297.             }        
  298.         }    
  299.     else {    
  300.         dir[0] = src[0];
  301.         return;
  302.     }
  303.     }    
  304.  
  305. if ((ptr = Malloc(sbyte)) == 0)
  306.     form_alert(1, "[3][ Can't Allocate | Memory! ][Cont]");
  307. else {
  308.     dir[0] = src[0];    /* Set drive to source    */              
  309.     if ((handle = Fopen(dir, 0x00)) < 0) {
  310.         cpynchar(alert8 + 4L, dir, 20);      
  311.         form_alert(1, alert8);
  312.         }
  313.     else {
  314.         if ((ret2 = Fread(handle, sbyte, ptr)) != sbyte) {
  315.             cpynchar(alertf + 4L, dir, 20);    
  316.             form_alert(1, alertf);
  317.             }
  318.         Fclose(handle);
  319.         dir[0] = dest[0];    /* Set drive to Destination    */              
  320.         if ((handle = Fcreate(dir, 0x00)) < 0) {
  321.             cpynchar(alert9 + 4L, dir, 20);      
  322.             form_alert(1, alert9);        
  323.             }
  324.         else {
  325.             if ((ret2 = Fwrite(handle, ret2, ptr)) < 0) {
  326.                 cpynchar(alertg + 4L, dir, 20);
  327.                 form_alert(1, alertg);
  328.                 }
  329.             Fclose(handle);
  330.             }
  331.         Mfree(ptr);
  332.         }
  333.     }    
  334.  
  335. dir[0] = src[0];    /* Set drive back to Source    */           
  336.  
  337. return;
  338.  
  339. }    
  340.  
  341. int cmp_datime(dt)
  342. int  *dt;
  343.  
  344. /*****************************************************************************
  345.  
  346.         Compare file time/date with backup date/time
  347.         
  348.        Return: TRUE (File needs to be backed up)
  349.                FALSE (File date earlier than backup date (no need to backup)
  350.     
  351. *****************************************************************************/
  352.  
  353. {
  354.  
  355. if ( type_update == ALL         ||
  356.      date_backup[1] < dt[1]     ||
  357.      ( date_backup[1] == dt[1]  &&  date_backup[0] <= dt[0] ) )
  358.     return(TRUE);
  359. else
  360.     return(FALSE);
  361.  
  362. }    
  363.  
  364. updat_ts()
  365.  
  366. /*****************************************************************************
  367.  
  368.     Update (delete, and create) or create timestamp file
  369.  
  370. ******************************************************************************/
  371.  
  372. {
  373. int    handle;        /* File Descriptor    */
  374. char    filenm[14];
  375. int    ret;
  376.  
  377. strcpy(filenm, src);
  378. strcat(filenm, "\\");
  379. strcat(filenm, FILENM);
  380.  
  381. if ( (ret = Fsfirst(filenm, 0x1f)) == E_OK )
  382.     if ( (ret = Fdelete(filenm)) != 0 ) {
  383.         form_alert(1, alertj);
  384.         return;
  385.         }
  386.  
  387. if ((handle = Fcreate(filenm, 0x00)) < 0)
  388.     form_alert(1, alertj);        
  389. else    
  390.     Fclose(handle);
  391. }
  392.  
  393. /***********************************************************************/
  394. /***********************************************************************/
  395. /*                                                                     */
  396. /*                       SCREEN  DISPLAYS                              */
  397. /*                                                                     */
  398. /***********************************************************************/
  399. /***********************************************************************/
  400.  
  401. /*------------------------------*/
  402. /*      pgm_init                */
  403. /*------------------------------*/
  404. WORD pgm_init()
  405. {
  406. static char winame[] = "    ******    Hard Disk Backup    ******    ";
  407. WORD    work_in[11];
  408. WORD    i;
  409.  
  410. ap_id = appl_init();            /* Initialize Libraries    */
  411. if ( ap_id == -1 )
  412.     return(4);
  413. wind_update(BEG_UPDATE);
  414. graf_mouse(HOUR_GLASS, 0x0L);
  415. if ( !rsrc_load( ADDR("BACKUP.RSC") ) ) {
  416.     graf_mouse(ARROW, 0x0L);
  417.     form_alert(ADDR("[3][Fatal Error !|BACKUP.RSC|File Not Found][ Abort ]"));
  418.     return(1);
  419.     }
  420.  
  421. /* open virtual workstation */
  422. /* allocate undo buffer */
  423. for ( i = 0; i < 10; i++ )
  424.     work_in[i] = 1;
  425. work_in[10] = 2;
  426. work_in[0] = ap_id;
  427. ph = graf_handle(&h,&w,&hh,&ww);
  428. v_opnvwk(work_in, &ph, work_out);
  429. if ( ph == 0 )
  430.     return(1);
  431.  
  432. wind_get(0,WF_WXYWH,&xdesk,&ydesk,&wdesk,&hdesk);
  433. wi_handle = wind_create(window_kind,xdesk,ydesk,wdesk,hdesk);
  434. if ( wi_handle == -1 ) {
  435.     form_alert(1, "[3][Bad Window Create!!][ABORT]");
  436.     return(3);
  437.     }
  438. wind_set(wi_handle,WF_NAME,winame,0,0);
  439. wind_open(wi_handle,xdesk,ydesk,wdesk,hdesk);
  440. clip[0] = xdesk;
  441. clip[1] = ydesk;
  442. clip[2] = wdesk;
  443. clip[3] = hdesk;
  444.  
  445. return(0);
  446. }
  447.  
  448. /*------------------------------*/
  449. /*      pgm_term                */
  450. /*------------------------------*/
  451. pgm_term(term_type)
  452. WORD    term_type;
  453. {
  454. switch (term_type) {     /* NOTE: all cases fall through         */
  455.     case (0 /* normal termination */):
  456.         wind_close(wi_handle);
  457.         wind_delete(wi_handle);
  458.     case (3):
  459.     case (2):
  460.         v_clsvwk( ph );
  461.     case (1):
  462.         wind_update(END_UPDATE);
  463.         appl_exit();
  464.     case (4):
  465.         break;
  466.     }
  467. }
  468.  
  469. int ask_scn()    /* Show Initial Screen And Ask For Continue    */
  470. {
  471. int xdial, ydial, wdial, hdial;
  472. int x = 0;
  473. int y = 0;
  474. int w = 0;
  475. int h = 0;
  476. int retn;
  477.  
  478. rsrc_gaddr(R_TREE, STRT, &tree);
  479. form_center(tree, &xdial, &ydial, &wdial, &hdial);
  480. form_dial(0, x, y, w, h, xdial, ydial, wdial, hdial);
  481. form_dial(1, x, y, w, h, xdial, ydial, wdial, hdial);
  482. objc_draw(tree, ROOT, MAX_DEPTH, xdial, ydial, wdial, hdial);
  483.  
  484. graf_mouse(ARROW, 0x0L);
  485. if ( form_do(tree, 0) == STRTCANC )
  486.     retn = 1;
  487. else
  488.     retn = 0;    
  489.  
  490. graf_mouse(HOUR_GLASS, 0x0L);
  491. form_dial(2, x, y, w, h, xdial, ydial, wdial, hdial);
  492. form_dial(3, x, y, w, h, xdial, ydial, wdial, hdial);
  493.  
  494. return(retn);
  495. }
  496.  
  497. get_parms()    /* Get Options from operator        */
  498. {
  499. int xdial, ydial, wdial, hdial;
  500. int x = 0;
  501. int y = 0;
  502. int w = 0;
  503. int h = 0;
  504. int retn;    /* Return From case call */
  505. long  avail_drives;
  506. long  drv_mask;
  507. int    fhandle;    /* File Descriptor    */
  508. char    filenm[14];
  509.  
  510. rsrc_gaddr(R_TREE, BACKUP, &tree);
  511. form_center(tree, &xdial, &ydial, &wdial, &hdial);
  512. form_dial(0, x, y, w, h, xdial, ydial, wdial, hdial);
  513. form_dial(1, x, y, w, h, xdial, ydial, wdial, hdial);
  514. objc_change(tree,VERNO, 0,xwork,ywork,wwork,hwork,SELECTED,1);
  515. objc_change(tree,FILE,0,xwork,ywork,wwork,hwork,SELECTED,1);
  516. objc_draw(tree, ROOT, MAX_DEPTH, xdial, ydial, wdial, hdial);
  517.  
  518. graf_mouse(ARROW, 0x0L);
  519.  
  520. for ( retn = -1; retn == -1; ) {
  521.     switch ( form_do(tree, SRC) ) {
  522.         case SRC:        /* Source Drive    */
  523.             break;
  524.         
  525.         case DEST:        /* Destination Drive    */
  526.             break;
  527.         
  528.         case FILE:        /* Backup by TIMESTMP.HD file timestamp    */
  529.             type_update = FILE;
  530.             objc_change(tree,FILE,0,xwork,ywork,wwork,hwork,SELECTED,1);
  531.             objc_change(tree,DATE,0,xwork,ywork,wwork,hwork,NORMAL,1);
  532.             objc_change(tree,ALL ,0,xwork,ywork,wwork,hwork,NORMAL,1);
  533.             break;
  534.         
  535.         case DATE:        /* Backup by Entered Date    */
  536.             type_update = DATE;
  537.             objc_change(tree,DATE,0,xwork,ywork,wwork,hwork,SELECTED,1);
  538.             objc_change(tree,FILE,0,xwork,ywork,wwork,hwork,NORMAL,1);
  539.             objc_change(tree,ALL ,0,xwork,ywork,wwork,hwork,NORMAL,1);
  540.             break;
  541.         
  542.         case ALL:        /* Backup ALL Files    */
  543.             type_update = ALL;
  544.             objc_change(tree,ALL,0,xwork,ywork,wwork,hwork,SELECTED,1);
  545.             objc_change(tree,FILE,0,xwork,ywork,wwork,hwork,NORMAL,1);
  546.             objc_change(tree,DATE,0,xwork,ywork,wwork,hwork,NORMAL,1);
  547.             break;
  548.         
  549.         case VERNO:        /* No verification on replace copy    */
  550.             autowrite = TRUE;
  551.             objc_change(tree,VERNO, 0,xwork,ywork,wwork,hwork,SELECTED,1);
  552.             objc_change(tree,VERYES,0,xwork,ywork,wwork,hwork,NORMAL,1);
  553.             break;
  554.         
  555.         case VERYES:    /* Verification on replace copy    */
  556.             autowrite = FALSE;
  557.             objc_change(tree,VERYES,0,xwork,ywork,wwork,hwork,SELECTED,1);
  558.             objc_change(tree,VERNO, 0,xwork,ywork,wwork,hwork,NORMAL,1);
  559.             break;
  560.         
  561.         case CANCEL:    /* No Copy - Exit Program    */
  562.             retn = 1;
  563.             break;
  564.         
  565.         case START:        /* Start Copy    */
  566.             rsrc_gaddr(R_TREE, BACKUP, &obj);
  567.             ted = (TEDINFO *)obj[SRC].ob_spec;
  568.             LBCOPY(src, ted->te_ptext, 1);
  569.             isrc = src[0] - '@';
  570.             ted = (TEDINFO *)obj[DEST].ob_spec;
  571.             LBCOPY(dest, ted->te_ptext, 1);
  572.             idest = dest[0] - '@';
  573.             if ( src[0] == dest[0] ) {
  574.             form_alert(1, "[3][       Source|        and|     Destination|Cannot by the same!!][ OK ]");
  575.                 objc_change(tree,START, 0,xwork,ywork,wwork,hwork,NORMAL,1);
  576.                 break;
  577.             }
  578.         avail_drives = Drvmap();    /* Get Available Drives    */
  579.         drv_mask = 1 << (isrc - 1);    /* See if source drive exists    */
  580.         if ( (avail_drives & drv_mask) == 0 ) {
  581.             form_alert(1, "[3][    Source Drive|  Does not exist!!][ OK ]");
  582.                 objc_change(tree,START, 0,xwork,ywork,wwork,hwork,NORMAL,1);
  583.                 break;
  584.             }
  585.         drv_mask = 1 << (idest - 1);    /* See if source drive exists    */
  586.         if ( (avail_drives & drv_mask) == 0 ) {
  587.             form_alert(1, "[3][  Destination Drive|  Does not exist!!][ OK ]");
  588.                 objc_change(tree,START, 0,xwork,ywork,wwork,hwork,NORMAL,1);
  589.                 break;
  590.             }
  591.         
  592.         if ( type_update == FILE ) {
  593.         strcpy(filenm, src);
  594.         strcat(filenm, "\\");
  595.         strcat(filenm, FILENM);
  596.         if ( (fhandle = Fopen(filenm, 0)) > 0 ) { /*See if file exists*/
  597.                 Fdatime(&date_backup, fhandle, 0);    /* Get date and time */
  598.                 Fclose(fhandle);
  599.                 }
  600.         else {    /* File doesn't exist */
  601.             form_alert(1, "[3][     TIMESTMP.HD|  Doesn't Exist on|    Source Drive|  Select Backup by|    DATE or ALL?][ CONTINUE ]");
  602.                     objc_change(tree,FILE,0,xwork,ywork,wwork,hwork,NORMAL,1);
  603.                     objc_change(tree,DATE,0,xwork,ywork,wwork,hwork,SELECTED,1);
  604.                     type_update = DATE;
  605.                     objc_change(tree,START, 0,xwork,ywork,wwork,hwork,NORMAL,1);
  606.                     break;
  607.                     }
  608.             }
  609.             retn = 0;    /* Source, Dest, & Type ok    */
  610.             break;
  611.         }
  612.     }
  613.  
  614. graf_mouse(HOUR_GLASS, 0x0L);
  615. form_dial(2, x, y, w, h, xdial, ydial, wdial, hdial);
  616. form_dial(3, x, y, w, h, xdial, ydial, wdial, hdial);
  617.  
  618. return(retn);
  619. }
  620.  
  621. opt_date()    /* Get Date from operator - If date Selected    */
  622. {
  623. int xdial, ydial, wdial, hdial;
  624. int x = 0;
  625. int y = 0;
  626. int w = 0;
  627. int h = 0;
  628. int retn;    /* Return From case call */
  629.  
  630. rsrc_gaddr(R_TREE, OPERDATE, &tree);
  631. form_center(tree, &xdial, &ydial, &wdial, &hdial);
  632. form_dial(0, x, y, w, h, xdial, ydial, wdial, hdial);
  633. form_dial(1, x, y, w, h, xdial, ydial, wdial, hdial);
  634. objc_draw(tree, ROOT, MAX_DEPTH, xdial, ydial, wdial, hdial);
  635.  
  636. graf_mouse(ARROW, 0x0L);
  637.  
  638. for ( retn = -1; retn == -1; ) {
  639.     switch ( form_do(tree, OPDATE) ) {
  640.         case OPDATE:        /* Get DATE    */
  641.             break;
  642.         
  643.         case OPTIME:        /* Get Time    */
  644.             break;
  645.         
  646.         case DOCANCEL:    /* No Copy - Exit Program    */
  647.             retn = 1;
  648.             break;
  649.         
  650.         case DOBAK:        /* Start Copy    */
  651.  
  652.             rsrc_gaddr(R_TREE, OPERDATE, &obj);
  653.             ted = (TEDINFO *)obj[OPDATE].ob_spec;
  654.             if ( conv_date(ted->te_ptext) == FALSE ) {
  655.                 form_alert(1, "[3][ Invalid Date!! ][ OK ]");
  656.                 objc_change(tree,DOBAK, 0,xwork,ywork,wwork,hwork,NORMAL,1);
  657.             }
  658.             else {
  659.                 ted = (TEDINFO *)obj[OPTIME].ob_spec;                
  660.                 if ( conv_time(ted->te_ptext) == FALSE ) {
  661.                     form_alert(1, "[3][ Invalid Time!! ][ OK ]");
  662.                     objc_change(tree,DOBAK, 0,xwork,ywork,wwork,hwork,NORMAL,1);
  663.                     }
  664.         else
  665.                     retn = 0;
  666.                 }    
  667.             break;
  668.         }
  669.     }
  670.  
  671. graf_mouse(HOUR_GLASS, 0x0L);
  672. form_dial(2, x, y, w, h, xdial, ydial, wdial, hdial);
  673. form_dial(3, x, y, w, h, xdial, ydial, wdial, hdial);
  674.  
  675. return(retn);
  676. }
  677.  
  678. int conv_date(string)    /* Convert string to date */
  679. char *string;
  680. {
  681. int mm, dd, yy;
  682.     
  683. if ( string[0] > '1'                          ||
  684.      (string[0] == '1'  &&  string[1] > '2')  ||
  685.      string[2] > '3'                          ||
  686.      (string[2] == '3'  &&  string[3] > '1') )    
  687.     return(FALSE);
  688.  
  689. mm = char2int(&string[0]) << 5;              
  690. dd = char2int(&string[2]);
  691. yy = char2int(&string[4]) + 1900;
  692.  
  693. if ( yy < 1980 )
  694.     yy = 0;
  695. else
  696.     yy = (yy - 1980) << 9;
  697. date_backup[1] = mm | dd | yy;
  698.        
  699. return(TRUE);    
  700. }
  701.  
  702. int conv_time(string)    /* Convert string to time    */
  703. char *string;
  704. {
  705.  
  706. int  hrs, min;
  707.     
  708. if ( string[0] > '2'                         ||
  709.      (string[0] == '2'  && string[1] > '3')  ||
  710.      string[2] > '5' )
  711.     return(FALSE);
  712.  
  713. hrs = char2int(&string[0]) << 11;              
  714. min = char2int(&string[2]) << 5;
  715. date_backup[0] = hrs | min;
  716. return(TRUE);    
  717. }
  718.  
  719. int char2int(string)    /* Convert 2 ascii numerics to an int    */
  720. char *string;
  721. {
  722. return( (string[0] & 0x0f) * 10 + (string[1] & 0x0f) );    
  723. }
  724.