home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / diskutil / mtools / buf_writ.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-05  |  3.0 KB  |  141 lines

  1. /*
  2.  * Do full cylinder buffered writes to slow devices.  Uses a simple
  3.  * buffered read/delayed write algorithm
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include "msdos.h"
  8.  
  9. extern int fd, disk_size, disk_dirty, dir_start, dir_len;
  10. extern int clus_size;
  11. extern long disk_offset, disk_current;
  12. extern unsigned char *disk_buf;
  13. static int blank_cyl();
  14.  
  15. void
  16. disk_write(start, buf, len)
  17. long start;
  18. unsigned char *buf;
  19. int len;
  20. {
  21.     register long i;
  22.     int length;
  23.     unsigned char *buf_ptr, *disk_ptr;
  24.     char *memcpy();
  25.     void perror(), exit(), disk_flush();
  26.     long where, tail, lseek();
  27.  
  28.                     /* don't use cache? */
  29.     if (disk_size == 1) {
  30.         where = (start * MSECTOR_SIZE) + disk_offset;
  31.         if (lseek(fd, where, 0) < 0) {
  32.             perror("disk_write: lseek");
  33.             exit(1);
  34.         }
  35.                     /* write it! */
  36.         if (write(fd, (char *) buf, (unsigned int) len) != len) {
  37.             perror("disk_write: write");
  38.             exit(1);
  39.         }
  40.         return;
  41.     }
  42.  
  43.     tail = start + (len / MSECTOR_SIZE) - 1;
  44.     for (i = start; i <= tail; i++) {
  45.                     /* a cache miss... */
  46.         if (i < disk_current || i >= disk_current + disk_size) {
  47.  
  48.             if (disk_dirty)
  49.                 disk_flush();
  50.  
  51.             /*
  52.              * If there is something on the new cylinder that
  53.              * you want to keep, you'll have to read it first
  54.              * before writing.
  55.              */
  56.             if (blank_cyl(i))
  57.                 disk_current = (i / disk_size) * disk_size;
  58.             else {
  59.                 disk_current = (i / disk_size) * disk_size;
  60.                 where = (disk_current * MSECTOR_SIZE) + disk_offset;
  61.                 length = disk_size * MSECTOR_SIZE;
  62.  
  63.                     /* move to next location */
  64.                 if (lseek(fd, where, 0) < 0) {
  65.                     perror("disk_write: lseek");
  66.                     exit(1);
  67.                 }
  68.                     /* read it! */
  69.                 if (read(fd, (char *) disk_buf, (unsigned int) length) != length) {
  70.                     perror("disk_write: read");
  71.                     exit(1);
  72.                 }
  73.             }
  74.         }
  75.                     /* a cache hit ... */
  76.         buf_ptr = buf + ((i - start) * MSECTOR_SIZE);
  77.         disk_ptr = disk_buf + ((i - disk_current) * MSECTOR_SIZE);
  78.         memcpy((char *) disk_ptr, (char *) buf_ptr, MSECTOR_SIZE);
  79.         disk_dirty = 1;
  80.     }
  81.     return;
  82. }
  83.  
  84. /*
  85.  * Flush a dirty buffer to disk.  Resets disk_dirty to zero.
  86.  * All errors are fatal.
  87.  */
  88.  
  89. void
  90. disk_flush()
  91. {
  92.     int len;
  93.     long where, lseek();
  94.     void perror(), exit();
  95.  
  96.     if (fd < 0 || disk_current < 0L || !disk_dirty)
  97.         return;
  98.  
  99.     where = (disk_current * MSECTOR_SIZE) + disk_offset;
  100.     if (lseek(fd, where, 0) < 0) {
  101.         perror("disk_flush: lseek");
  102.         exit(1);
  103.     }
  104.                     /* write it! */
  105.     len = disk_size * MSECTOR_SIZE;
  106.     if (write(fd, (char *) disk_buf, (unsigned int) len) != len) {
  107.         perror("disk_flush: write");
  108.         exit(1);
  109.     }
  110.     disk_dirty = 0;
  111.     return;
  112. }
  113.  
  114. /*
  115.  * Determine if the cylinder has some useful information on it.  Returns a 1
  116.  * if it is blank.
  117.  */
  118.  
  119. static int
  120. blank_cyl(num)
  121. long num;
  122. {
  123.     register unsigned int i;
  124.     unsigned int start, end, fat_decode();
  125.     long sector;
  126.  
  127.     sector = (num / disk_size) * disk_size;
  128.     if (!sector)
  129.         return(0);
  130.  
  131.     start = ((sector - dir_start - dir_len) / clus_size) + 2;
  132.     end = ((sector + disk_size - dir_start - dir_len) / clus_size) + 2;
  133.  
  134.     for (i = start; i < end; i++) {
  135.                     /* if fat_decode returns non-zero */
  136.         if (fat_decode(i))
  137.             return(0);
  138.     }
  139.     return(1);
  140. }
  141.