home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 5 / 05.iso / a / a013 / 1.ddi / SOURCE.EXE / F_SYSSAV.PRG < prev    next >
Encoding:
Text File  |  1991-01-25  |  19.5 KB  |  735 lines

  1. *****************************************************************
  2. FUNCTION SYSSAVE
  3. *****************************************************************
  4.  
  5. * Back up and restore data files from Clipper
  6.  
  7. * Copyright(c) 1991 -- James Occhiogrosso
  8.  
  9. # include 'box.ch'
  10. # include 'inkey.ch'
  11. # include 'set.ch'
  12. # include 'setcurs.ch'
  13.  
  14. # define drive_num  ASC(drive) - 64
  15. # define K_f        102
  16. # define K_F         70
  17.  
  18. LOCAL old_cursor := SETCURSOR(SC_NONE), old_screen := '', ;
  19.       old_dateset := SET(_SET_DATEFORMAT)
  20.  
  21. PARAMETERS mode, drive, filelist, msg_line
  22.  
  23. * Initialize all variables
  24.  
  25. PRIVATE initsize := needed := ret_value := remaining ;
  26.         := total := shandle := size := thandle := 0
  27.  
  28. PRIVATE backfile := backtext := backupid := buffer :=  ;
  29.         disktext := sourcetime := source := target := ''
  30.  
  31. PRIVATE diskno := 1, sourcedate
  32.  
  33. * Test critical passed arguments
  34.  
  35. IF PCOUNT()< 2 .OR. TYPE('mode') != 'N' .OR. TYPE('drive') != 'C'
  36.     * Wrong parameters passed, return error
  37.     RETURN -1
  38. ENDIF
  39.  
  40. IF mode < 1 .OR. mode > 4
  41.     * Check mode passed. If not between 1 and 4, return error
  42.     RETURN -1
  43. ENDIF
  44.  
  45. IF (mode = 1 .OR. mode = 3) .AND. TYPE('filelist') != 'A'
  46.     * Both "Backup" modes require a filelist array
  47.     RETURN -1
  48. ENDIF
  49.  
  50. * Set up default message line if not passed
  51. IF msg_line = NIL
  52.     msg_line = MAXROW()
  53. ENDIF
  54.  
  55. * Save screen area
  56. IF mode < 3
  57.     * Full screen mode
  58.     IF MEMORY(1) <= 8
  59.         * Insufficient memory to run in full screen mode
  60.         ?? CHR(7)
  61.         CENTERON(msg_line, 'Insufficient memory to run. ' + ;
  62.                             hitanykey)
  63.         INKEY(0)
  64.         RETURN (1)
  65.     ELSE
  66.         old_screen = SCRNSAVE(0, 0, msg_line, MAXCOL())
  67.     ENDIF
  68. ELSE
  69.     * Single line screen mode
  70.     old_screen = SCRNSAVE(msg_line, 0, msg_line, MAXCOL())
  71. ENDIF
  72.  
  73. * Strip all but first character of drive passed
  74. drive = UPPER(LEFT(drive,1)) + ':'
  75.  
  76. backfile = drive + "BACKUP" + LTRIM(STR(diskno)) + ".DAT"
  77.  
  78. IF mode = 1 .OR. mode = 2        && Full screen modes
  79.     CLEAR
  80.     @ 3, 0
  81.     TEXT
  82.          This function uses the DOS FORMAT program if it detects
  83.          an unformatted disk during a BACKUP operation.
  84.  
  85.          FORMAT.COM must be present in the directory or on the 
  86.          DOS path, or the process will abort.
  87.  
  88.          Label and number all disks during BACKUP according to
  89.          the screen instructions. Improperly numbering a disk 
  90.          may cause serious problems!
  91.  
  92.          When restoring, be sure to load the numbered disks in 
  93.          the sequence shown in the screen instructions.
  94.  
  95.     ENDTEXT
  96.  
  97.     SETCOLOR(colbarhi)
  98.     @ 18, 7, 20, 72 BOX B_SINGLE + SPACE(1)
  99.     @ 19, 9 SAY 'CAUTION: Files in current directory on drive ';
  100.                 + drive + ' will be erased.'
  101.     SETCOLOR(colstd)
  102. ENDIF
  103.  
  104.  
  105. * Allocate copy buffer 1/4 of available free memory
  106. initsize = (MEMORY(1) * 1024)/ 4
  107.  
  108. * Return if initial buffer size less than 2K
  109. IF initsize <= 2048
  110.      ?? CHR(7)
  111.      CENTERON(msg_line, 'Insufficient memory to run. ' + ;
  112.                          hitanykey)
  113.      INKEY(0)
  114.      RETURN(1)
  115. ENDIF
  116.  
  117. * Initialize copy buffer size
  118. size = initsize
  119. buffer = SPACE(size)
  120.  
  121. IF mode = 1 .OR. mode = 3
  122.  
  123.     * If this is a backup operation, check files in passed array
  124.     * by checking size. FILESIZE returns -1 on any file error.
  125.  
  126.     num_files = LEN(filelist)
  127.     FOR cntr = 1 to num_files
  128.          curr_file = FILESIZE(filelist[cntr])
  129.          IF curr_file <= 0
  130.              CENTERON(msg_line, 'Error reading file ' +  ;
  131.                       filelist[cntr] + '. ' + hitanykey)
  132.              INKEY(0)
  133.              RETURN(5)
  134.          ENDIF
  135.          needed = needed + curr_file
  136.     NEXT
  137.  
  138.     * Advise operator of disk space needed for backup operation
  139.     SETCURSOR(SC_INSERT)
  140.     CENTERON(msg_line, 'Backup will need approximately '  + ;
  141.                         LTRIM(STR(INT((needed/1024) + 2))) + ;
  142.                        'K of disk space.  Proceed? Y/N     ')
  143. ELSE
  144.     CENTERON(msg_line, 'Proceed with restore operation? Y/N   ')
  145. ENDIF
  146.  
  147. @ msg_line, COL() -4 SAY ''
  148. IF .NOT. OPCONFIRM()
  149.     * Operator aborted
  150.     SCRNREST(old_screen)
  151.     SETCURSOR(old_cursor)
  152.     RETURN(0)
  153. ENDIF
  154.  
  155. * Ask operator to insert a disk
  156. SETCURSOR(SC_NONE)
  157. DO INSERTDISK
  158. IF LASTKEY() = K_ESC
  159.     SCRNREST(old_screen)
  160.     SETCURSOR(old_cursor)
  161.     RETURN(0)
  162. ENDIF
  163.  
  164. * Perform selected operation.
  165. IF mode = 1 .OR. mode = 3
  166.     DO BACKUP
  167. ELSE
  168.     DO RESTORE
  169. ENDIF
  170.  
  171. * Restore everything and return
  172. SCRNREST(old_screen)
  173. SETCURSOR(old_cursor)
  174. SET(_SET_DATEFORMAT, old_dateset)
  175. RETURN(ret_value)
  176.  
  177. *****************************************************************
  178. STATIC PROCEDURE BACKUP
  179. *****************************************************************
  180.  
  181. * Backup files to selected drive
  182.  
  183. LOCAL counter := 1, disk_free := 0
  184.  
  185. * Checkout and clear disk
  186. DO NEWDISK
  187.  
  188. IF LASTKEY() = K_ESC
  189.     * Abort if Esc terminated any operation
  190.     ret_value = 12
  191.     RETURN
  192. ENDIF
  193.  
  194. SET CENTURY OFF
  195. backupid = DTOC(DATE()) + ' ' + TIME() + ' '
  196. backtext = backupid
  197.  
  198. DO WHILE counter <= LEN(filelist)
  199.  
  200.     * Get the file to backup and create target file name.
  201.     source = LTRIM(UPPER(filelist[counter]))
  202.     target = UPPER(drive) + source
  203.  
  204.     * Open files
  205.     IF .NOT. OPENSOURCE() .OR. .NOT. OPENTARGET()
  206.         ret_value = 2
  207.         RETURN
  208.     ENDIF
  209.  
  210.     CENTERON(msg_line, 'Backing up file '+ source +' to drive ' ;
  211.                   + drive + ' - Disk No. ' + LTRIM(STR(diskno)))
  212.  
  213.     DO WHILE (remaining > 0)
  214.  
  215.         * Check disk space remaining
  216.         disk_free = DISKSPACE(drive_num)
  217.  
  218.         IF disk_free <= 2048
  219.             * Reset everything and get new disk
  220.             size := initsize
  221.             buffer := ''
  222.             buffer := SPACE(size)
  223.  
  224.             * Close partial target file and date it
  225.             FCLOSE(thandle)
  226.             IF EMPTY(FILEDATE(target,sourcedate)) .OR. ;
  227.                      EMPTY(FILETIME(target,sourcetime))
  228.  
  229.                * Empty return is error in writing date or time
  230.                 CENTERON(msg_line, ;
  231.                  'Error writing file date or time to ' + target)
  232.                 ?? CHR(7)
  233.                 ret_value = 6
  234.                 RETURN
  235.             ENDIF
  236.  
  237.             * Add + to target file name if copy incomplete
  238.  
  239.             backfile = drive +"BACKUP"+ LTRIM(STR(diskno))+".DAT"
  240.             backtext = backtext + SUBSTR(target,3) + '+ '
  241.             IF .NOT. MEMOWRIT(backfile,backtext)
  242.                 CENTERON(msg_line, ;
  243.                 'Error writing backup identification file')
  244.                 ?? CHR(7)
  245.                 ret_value = 7
  246.                 RETURN
  247.             ENDIF
  248.  
  249.             * Prepare next disk
  250.             backtext = backupid
  251.             diskno++
  252.             DO INSERTDISK
  253.             DO NEWDISK
  254.             IF LASTKEY() = K_ESC
  255.                 * Abort if Esc terminated any operation
  256.                 ret_value = 12
  257.                 RETURN
  258.             ENDIF
  259.  
  260.             * Create target file on new disk
  261.             thandle = FCREATE(target)
  262.             IF FERROR() > 0
  263.                 CENTERON(msg_line, ;
  264.                 'Fatal error! Cannot create file '+ target)
  265.                 ?? CHR(7)
  266.                 ret_value = 6
  267.                 RETURN
  268.             ENDIF
  269.             * Re-display current backup file/disk information
  270.             CENTERON(msg_line, ;
  271.             'Backing up file ' + source + ' to drive ' ;
  272.             + drive + ' - Disk No. ' + LTRIM(STR(diskno)))
  273.  
  274.         ELSE
  275.             * Reset buffer size
  276.             IF disk_free - 2048 > initsize
  277.                size = initsize
  278.             ELSE
  279.                size = disk_free - 2048
  280.             ENDIF
  281.             buffer := ''
  282.             buffer := SPACE(size)
  283.         ENDIF
  284.  
  285.         IF .NOT. COPYBUFFER()
  286.              RETURN
  287.         ENDIF
  288.     ENDDO
  289.  
  290.     * Done! Close files
  291.     IF .NOT. CLOSEFILES()
  292.         RETURN
  293.     ENDIF
  294.  
  295.     * Add ! to target if complete
  296.  
  297.     backfile = drive + "BACKUP" + LTRIM(STR(diskno)) + ".DAT"
  298.     backtext = backtext + SUBSTR(target,3) + '! '
  299.     IF .NOT. MEMOWRIT(backfile,backtext)
  300.         CENTERON(msg_line, 'Error writing backup data file')
  301.         ?? CHR(7)
  302.         ret_value = 7
  303.         RETURN
  304.     ENDIF
  305.  
  306.     * Set up for next file in array
  307.     counter++
  308.  
  309. ENDDO WHILE counter <= LEN(filelist)
  310. RETURN
  311.  
  312. *****************************************************************
  313. STATIC PROCEDURE RESTORE
  314. *****************************************************************
  315. * Restore backed up files
  316.  
  317. LOCAL splitfile := .F.
  318. diskno = 1
  319.  
  320. * Verify correct restore disk
  321. IF .NOT. CHECKNEXT()
  322.     RETURN
  323. ENDIF
  324.  
  325. DO WHILE LEN(backtext) > 0
  326.     IF .NOT. splitfile
  327.  
  328.         * Get source and target file names
  329.         IF AT("!", backtext) > 0
  330.             target = SUBSTR(backtext, 1, AT("!", backtext) -1 )
  331.         ELSEIF AT("+", backtext) > 0
  332.             target = SUBSTR(backtext, 1, AT("+", backtext) -1 )
  333.         ENDIF
  334.         source = drive + target
  335.  
  336.         * Open files
  337.         IF .NOT. OPENSOURCE() .OR. .NOT. OPENTARGET()
  338.             EXIT
  339.         ENDIF
  340.     ENDIF
  341.  
  342.     * Strip file name from list.
  343.     backtext = SUBSTR(backtext,LEN(target)+1)
  344.     CENTERON(msg_line, ;
  345.     'Restoring file ' + source + ' to hard disk.')
  346.  
  347.     * If marker is "!", copy is a complete file
  348.     IF ASC(backtext) = 33
  349.         splitfile = .F.
  350.         DO WHILE remaining > 0
  351.             IF .NOT. COPYBUFFER()
  352.                 EXIT
  353.             ENDIF
  354.         ENDDO
  355.         * Strip file marker and space
  356.         backtext = SUBSTR(backtext,3)   
  357.  
  358.     * If marker is "+", copy is a split file
  359.  
  360.     ELSEIF  ASC(backtext) = 43
  361.         * Copy first disk unconditionally
  362.         IF .NOT. splitfile     
  363.             DO WHILE remaining > 0
  364.                 IF .NOT. COPYBUFFER()
  365.                     EXIT
  366.                 ENDIF
  367.             ENDDO
  368.         ENDIF
  369.         diskno = diskno + 1
  370.         splitfile = .T.
  371.  
  372.         * Close source file on old disk
  373.         FCLOSE(shandle)
  374.         DO INSERTDISK
  375.  
  376.         * Reinitialize memory variables for next disk
  377.         IF CHECKNEXT()
  378.  
  379.             * Reopen source file on new disk
  380.             IF .NOT. OPENSOURCE()
  381.                 EXIT
  382.             ENDIF
  383.  
  384.             * Continue copying source
  385.             DO WHILE remaining > 0
  386.                 CENTERON(msg_line, 'Restoring file ' + source + ;
  387.                          ' to hard disk.')
  388.                 IF .NOT. COPYBUFFER()
  389.                     EXIT
  390.                 ENDIF
  391.             ENDDO
  392.         ELSE
  393.             * Operator terminated with Esc
  394.             ret_value = 12
  395.             EXIT
  396.         ENDIF
  397.     ENDIF
  398.  
  399.     IF .NOT. splitfile .OR. (splitfile .AND. ;
  400.              SUBSTR(backtext,LEN(target)+1,1) = '!')
  401.  
  402.         * Copy complete. Close and date target
  403.         IF .NOT. CLOSEFILES()
  404.             RETURN
  405.         ENDIF
  406.     ENDIF
  407. ENDDO
  408. @ msg_line, 0
  409. RETURN
  410.  
  411. *****************************************************************
  412. STATIC PROCEDURE NEWDISK
  413. *****************************************************************
  414. * Check disk drive status and space
  415.  
  416. LOCAL cnt := delcnt := errorcode := keypress := 0, delfiles := {}
  417.  
  418. * Activate interrupt 24 handler
  419. SETINT24(.T.)
  420.  
  421. DO WHILE .T.
  422.     SETCOLOR(colhelp1)
  423.  
  424.     * Check for disk error
  425.     FCLOSE(FCREATE(backfile))
  426.     errorcode = GETINT24()
  427.  
  428.     IF errorcode = 1 .OR. errorcode = 3
  429.         IF errorcode = 1
  430.             CENTERON(msg_line, 'Disk in drive ' + drive + ;
  431.                      ' is write protected. '  + hitanykey)
  432.         ELSE
  433.             CENTERON(msg_line, ;
  434.             'Drive ' + drive + ' not ready. '+ hitanykey)
  435.         ENDIF
  436.         * Wait for operator to correct problem or abort
  437.         ?? CHR(7)
  438.         IF INKEY(0) != K_ESC
  439.             LOOP
  440.         ELSE
  441.             ret_value = 12
  442.             EXIT
  443.         ENDIF
  444.     ENDIF
  445.  
  446.     IF errorcode = 13
  447.         CENTERON(msg_line, ;
  448.         'Disk is Unformatted. Press F to format it, ' + ;
  449.                               'or any key to try again.')
  450.         ?? CHR(7)
  451.         keypress = INKEY(0)
  452.         IF keypress = K_ESC
  453.             * Operator aborted
  454.             ret_value = 12
  455.             EXIT
  456.         ELSEIF keypress = K_F .OR. keypress = K_f
  457.             IF FILE("FORMAT.COM") .OR. FILE("FORMAT.EXE") .OR. ;
  458.                       FILE("FORMAT.BAT") .AND. .NOT. EMPTY(drive)
  459.                 SAVE SCREEN
  460.                 CLEAR
  461.                 @ 1,0 SAY 'Running DOS format. ' + ;
  462.                           'Follow screen instructions'
  463.                 ?
  464.                 ?
  465.                 RUN FORMAT &drive
  466.                 RESTORE SCREEN
  467.             ELSE
  468.                * DOS Format file missing
  469.                CENTERON(msg_line, ;
  470.                'Format program not on DOS path. ' + ;
  471.                'Cannot proceed.')
  472.                ?? CHR(7)
  473.                PAUSE(2)
  474.                * Force return to main menu on exit
  475.                KEYBOARD CHR(K_ESC)
  476.                ret_value = 11
  477.                EXIT
  478.             ENDIF
  479.         ELSE
  480.             * Operator pressed a key. Restart for disk change
  481.             LOOP
  482.         ENDIF
  483.  
  484.     ELSEIF errorcode > 0
  485.         CENTERON(msg_line, ;
  486.          'Unknown error -- Press any key to abort')
  487.         ?? CHR(7)
  488.         INKEY(0)
  489.         ret_value = 12
  490.     ELSE
  491.         * No errors. Delete files in root directory
  492.         CENTERON(msg_line, ;
  493.         'Erasing files on disk in drive ' + drive)
  494.         delcnt = ADIR(drive + "*.*")
  495.         IF delcnt > 0
  496.             ASIZE(delfiles,delcnt)
  497.             ADIR(drive + "*.*", delfiles)
  498.             FOR cnt = 1 to delcnt
  499.                 * Erase all files except COMMAND.COM
  500.                 IF delfiles[cnt] != 'COMMAND.COM'
  501.                     FERASE(drive + delfiles[cnt])
  502.                 ENDIF
  503.             NEXT
  504.         ENDIF
  505.  
  506.         * Check to see if all files were erased
  507.         IF DISKSIZE(drive_num) != DISKSPACE(drive_num)
  508.             ?? CHR(7)
  509.             SETCURSOR(SC_INSERT)
  510.             CENTERON(msg_line, ;
  511.             'All files on disk were not erased! ' +  ;
  512.             'Do you want to change disks?    ')
  513.  
  514.             * Position cursor and wait for operator
  515.             SETPOS(ROW(), COL()-2)
  516.             IF OPCONFIRM()
  517.                 SETCURSOR(SC_NONE)
  518.                 CENTERON(msg_line,'Insert new disk. '+ hitanykey)
  519.                 INKEY(0)
  520.                 LOOP
  521.             ELSE
  522.                 SETCURSOR(SC_NONE)
  523.                 CENTERON(msg_line, ;
  524.                          hitanykey + ' (or Esc to abort)' )
  525.                 INKEY(0)
  526.             ENDIF
  527.  
  528.         ENDIF
  529.         EXIT
  530.     ENDIF
  531.  
  532. ENDDO
  533.  
  534. SETINT24(.F.)
  535. SETCOLOR(colstd)
  536. @ msg_line, 0
  537. RETURN
  538.  
  539. *****************************************************************
  540. STATIC FUNCTION CHECKNEXT
  541. *****************************************************************
  542. * Test and initialize parameters for next restore disk
  543.  
  544. LOCAL errorcode := 0
  545.  
  546. * Activate interrupt 24 handler
  547. SETINT24(.T.)
  548.  
  549. DO WHILE .T.
  550.     * Check for disk error
  551.     DISKSPACE(drive_num)
  552.     errorcode = GETINT24()
  553.  
  554.     IF errorcode > 0
  555.         CENTERON(msg_line, ;
  556.         'Drive ' + drive + ' not ready. ' + hitanykey)
  557.         ?? CHR(7)
  558.         IF INKEY(0) != K_ESC
  559.             LOOP
  560.         ELSE
  561.             * Operator aborted
  562.             ret_value = 12
  563.             RETURN(.F.)
  564.         ENDIF
  565.     ENDIF
  566.     EXIT
  567. ENDDO
  568.  
  569. * Clear the INT24 handler
  570. SETINT24(.F.)
  571.  
  572. * Verify disk number
  573. backfile = drive + "BACKUP" + LTRIM(STR(diskno)) + ".DAT"
  574. DO WHILE .NOT. FILE(backfile)
  575.     CENTERON(msg_line, ;
  576.     'Incorrect disk ID or disk is not a backup disk. ' + ;
  577.                         hitanykey)
  578.     INKEY(0)
  579.     DO INSERTDISK
  580.     IF LASTKEY() = K_ESC
  581.         ret_value = 12
  582.         RETURN(.F.)
  583.     ENDIF
  584. ENDDO
  585.  
  586. * Read disk's backup identification file
  587. disktext = MEMOREAD(backfile)
  588. IF diskno = 1
  589.     backupid = SUBSTR(disktext, 1, 17)
  590. ELSE
  591.     * If not disk 1, verify it
  592.     DO WHILE .NOT. backupid == SUBSTR(disktext, 1, 17) .OR. ; 
  593.              .NOT. target == SUBSTR(disktext, 19, LEN(target))
  594.         CENTERON(msg_line, 'Disk ID invalid! - ' + hitanykey + ;
  595.                  ' (Esc to exit)' )
  596.         ?? CHR(7)
  597.         IF INKEY(0) = K_ESC
  598.             ret_value = 12
  599.             RETURN(.F.)
  600.         ENDIF
  601.     ENDDO
  602. ENDIF
  603. @ msg_line, 0
  604. backtext = SUBSTR(disktext, 19)
  605. RETURN(.T.)
  606. *
  607.  
  608. *****************************************************************
  609. STATIC FUNCTION OPENSOURCE
  610. *****************************************************************
  611. * Open source file
  612.  
  613. * Get date and time of source files
  614. sourcedate = FILEDATE(source)
  615. sourcetime = FILETIME(source)
  616.  
  617. * Verify that everything is readable
  618. IF EMPTY(sourcedate) .OR. EMPTY(sourcetime)
  619.     ?? CHR(7)
  620.     CENTERON(msg_line, ;
  621.     'Error verifying ' + source + ' file. ' + hitanykey)
  622.     ret_value = 3
  623.     INKEY(0)
  624.     RETURN(.F.)
  625. ENDIF
  626.  
  627. shandle = FOPEN(source)
  628. * Open all files and check for errors
  629. IF FERROR() > 0
  630.     * Source error
  631.     CENTERON(msg_line, 'Fatal error! Cannot open file ' ;
  632.              + source + ' ' + hitanykey)
  633.     ?? CHR(7)
  634.     INKEY(0)
  635.     ret_value = 2
  636.     RETURN(.F.)
  637. ENDIF
  638.  
  639. * Get total source file size.
  640. total = FSEEK(shandle, 0, 2)
  641. remaining = total
  642.  
  643. * Reset file pointer to BOF
  644. FSEEK(shandle, 0)
  645. RETURN(.T.)
  646.  
  647. *****************************************************************
  648. STATIC FUNCTION OPENTARGET
  649. *****************************************************************
  650. * Open target file
  651.  
  652. thandle = FCREATE(target)
  653. IF FERROR() > 0
  654.     * Target error
  655.     CENTERON(msg_line, 'Fatal error! Cannot create file ' ;
  656.              + target + ' ' + hitanykey)
  657.     ?? CHR(7)
  658.     ret_value = 4
  659.     INKEY(0)
  660.     RETURN(.F.)
  661. ENDIF
  662. RETURN(.T.)
  663.  
  664. *****************************************************************
  665. STATIC FUNCTION CLOSEFILES
  666. *****************************************************************
  667. * Close source and target files - redate target
  668.  
  669. FCLOSE(thandle)
  670. FCLOSE(shandle)
  671. * Write date and time to target file before closing
  672.  
  673. IF EMPTY(FILEDATE(target,sourcedate)) .OR. ;
  674.    EMPTY(FILETIME(target,sourcetime))
  675.     * Error occurred in writing date or time.
  676.     CENTERON(msg_line, ;
  677.     'Error writing file date ' + target + ' ' + hitanykey)
  678.     INKEY(0)
  679.     ret_value = 10
  680.     RETURN(.F.)
  681. ENDIF
  682.  
  683. @ msg_line, 0
  684. RETURN(.T.)
  685.  
  686. *****************************************************************
  687. STATIC FUNCTION COPYBUFFER
  688. *****************************************************************
  689. * Write buffer area to target disk
  690.  
  691. size = LEN(buffer)
  692. IF (remaining < size)
  693.     * Set size to remaining bytes in file
  694.     size = remaining
  695. ENDIF
  696.  
  697. * Read "size" bytes into buffer and check number read
  698. IF FREAD(shandle, @buffer, size) != size
  699.     ?? CHR(7)
  700.     CENTERON(msg_line, ;
  701.     "Fatal error reading " + source + ' ' + hitanykey)
  702.     INKEY(0)
  703.     ret_value = 8
  704.     RETURN(.F.)
  705. ENDIF
  706.  
  707. * Write "size" bytes to target and check number written
  708. IF FWRITE(thandle, buffer, size) != size
  709.     ?? CHR(7)
  710.     CENTERON(msg_line,  ;
  711.     "Fatal error writing " + target + ' ' + hitanykey)
  712.     INKEY(0)
  713.     ret_value = 9
  714.     RETURN(.F.)
  715. ENDIF
  716.  
  717. * Compute remaining bytes in file
  718. remaining = remaining - size
  719. RETURN(.T.)
  720.  
  721. *****************************************************************
  722. STATIC PROCEDURE INSERTDISK
  723. *****************************************************************
  724. * Display message and wait for operator to insert a disk
  725.  
  726. CENTERON(msg_line, ;
  727.          'Insert backup disk # ' + LTRIM(STR(diskno)) + ;
  728.          ' in drive ' + drive + '. ' + hitanykey)
  729. DONEBEEP()
  730. INKEY(0)
  731. @ msg_line, 0
  732. RETURN
  733.  
  734.  
  735.