home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / CMDS / mtools_3.6.src.lzh / MTOOLS_3.6 / init.c < prev    next >
Text File  |  1997-11-12  |  6KB  |  281 lines

  1. /*
  2.  * Initialize an MSDOS diskette.  Read the boot sector, and switch to the
  3.  * proper floppy disk device to match the format on the disk.  Sets a bunch
  4.  * of global variables.  Returns 0 on success, or 1 on failure.
  5.  */
  6.  
  7. #include "sysincludes.h"
  8. #include "msdos.h"
  9. #include "stream.h"
  10. #include "mtools.h"
  11. #include "fsP.h"
  12. #include "plain_io.h"
  13. #include "xdf_io.h"
  14. #include "buffer.h"
  15.  
  16. extern int errno;
  17.  
  18.  
  19. #define FULL_CYL
  20.  
  21. unsigned int num_clus;            /* total number of cluster */
  22.  
  23. #ifndef linux
  24. #define BOOTSIZE 512
  25. #else
  26. #define BOOTSIZE 256
  27. #endif
  28.  
  29.  
  30. /*
  31.  * Read the boot sector.  We glean the disk parameters from this sector.
  32.  */
  33. static int read_boot(Stream_t *Stream, struct bootsector * boot)
  34. {    
  35.     /* read the first sector, or part of it */
  36.     if (force_read(Stream, (char *) boot, 0, BOOTSIZE) !=
  37.         BOOTSIZE)
  38.         return -1;
  39.     return 0;
  40. }
  41.  
  42. static int fs_flush(Stream_t *Stream)
  43. {
  44.     DeclareThis(Fs_t);
  45.  
  46.     fat_write(This);
  47.     return 0;
  48. }
  49.  
  50. Class_t FsClass = {
  51.     read_pass_through, /* read */
  52.     write_pass_through, /* write */
  53.     fs_flush, 
  54.     0, /* free */
  55.     0, /* set geometry */
  56.     get_data_pass_through
  57. };
  58.  
  59. static int get_media_type(Stream_t *St, struct bootsector *boot)
  60. {
  61.     int media;
  62.  
  63.     media = boot->descr;
  64.     if(media < 0xf0){
  65.         char temp[512];
  66.         /* old DOS disk. Media descriptor in the first FAT byte */
  67.         /* old DOS disk always have 512-byte sectors */
  68.         if (force_read(St,temp,512,512) == 512)
  69.             media = (unsigned char) temp[0];
  70.         else
  71.             media = 0;
  72.     } else
  73.         media += 0x100;
  74.     return media;
  75. }
  76.  
  77.  
  78. Stream_t *GetFs(Stream_t *Fs)
  79. {
  80.     while(Fs && Fs->Class != &FsClass)
  81.         Fs = Fs->Next;
  82.     return Fs;
  83. }
  84.  
  85. Stream_t *find_device(char drive, int mode, struct device *out_dev,
  86.               struct bootsector *boot,
  87.               char *name, int *media)
  88. {
  89.     char errmsg[80];
  90.     Stream_t *Stream;
  91.     struct device *dev;
  92.  
  93.     Stream = NULL;
  94.     sprintf(errmsg, "Drive '%c:' not supported", drive);    
  95.                     /* open the device */
  96.     for (dev=devices; dev->name; dev++) {
  97.         FREE(&Stream);
  98.         if (dev->drive != drive)
  99.             continue;
  100.         *out_dev = *dev;
  101.         expand(dev->name,name);
  102.  
  103. #ifdef USE_XDF
  104.         Stream = XdfOpen(out_dev, name, mode, errmsg, 0);
  105. #else
  106.         Stream = 0;
  107. #endif
  108.  
  109.         if (!Stream)
  110.             Stream = SimpleFileOpen(out_dev, dev, name, mode,
  111.                         errmsg, 0);
  112.         else
  113.             out_dev->use_2m = 0x7f;
  114.  
  115.         if( !Stream)
  116.             continue;
  117.  
  118.         /* read the boot sector */
  119.         if (read_boot(Stream, boot)){
  120.             sprintf(errmsg,
  121.                 "init %c: could not read boot sector",
  122.                 drive);
  123.             continue;
  124.         }
  125.  
  126.         if((*media= get_media_type(Stream, boot)) <= 0xf0 ){
  127.             sprintf(errmsg,"init %c: unknown media type", drive);
  128.             continue;
  129.         }
  130.  
  131.         /* set new parameters, if needed */
  132.         errno = 0;
  133.         if(SET_GEOM(Stream, out_dev, dev, *media, boot)){
  134.             sprintf(errmsg, "Can't set disk parameters for %c: %s", 
  135.                 drive, strerror(errno));
  136.             continue;
  137.         }
  138.         break;
  139.     }
  140.  
  141.     /* print error msg if needed */    
  142.     if ( dev->drive == 0 ){
  143.         FREE(&Stream);
  144.         fprintf(stderr,"%s\n",errmsg);
  145.         return NULL;
  146.     }
  147.     return Stream;
  148. }
  149.  
  150.  
  151. Stream_t *fs_init(char drive, int mode)
  152. {
  153.     int media,i;
  154.     int nhs;
  155.     int disk_size = 0;    /* In case we don't happen to set this below */
  156.     size_t tot_sectors;
  157.     char name[EXPAND_BUF];
  158.     int cylinder_size;
  159.     struct device dev;
  160.  
  161.     struct bootsector boot0;
  162. #define boot (&boot0)
  163.     Fs_t *This;
  164.  
  165.     This = New(Fs_t);
  166.     if (!This)
  167.         return NULL;
  168.  
  169.     This->Direct = NULL;
  170.     This->Next = NULL;
  171.     This->refs = 1;
  172.     This->Buffer = 0;
  173.     This->Class = &FsClass;
  174.     This->drive = drive;
  175.  
  176.     This->Direct = find_device(drive, mode, &dev, &boot0, name, &media);
  177.     if(!This->Direct)
  178.         return NULL;
  179.     
  180.     This->sector_size = WORD(secsiz);
  181.     if(This->sector_size > MAX_SECTOR){
  182.         fprintf(stderr,"init %c: sector size too big\n", drive);
  183.         return NULL;
  184.     }
  185.  
  186.     cylinder_size = dev.heads * dev.sectors;
  187.     This->serialized = 0;
  188.     if ((media & ~7) == 0xf8){
  189.         i = media & 3;
  190.         This->cluster_size = old_dos[i].cluster_size;
  191.         tot_sectors = cylinder_size * old_dos[i].tracks;
  192.         This->fat_start = 1;
  193.         This->fat_len = old_dos[i].fat_len;
  194.         This->dir_len = old_dos[i].dir_len;
  195.         This->num_fat = 2;
  196.         This->sector_size = 512;
  197.         This->fat_bits = 12;
  198.         nhs = 0;
  199.     } else {
  200.         /*
  201.          * all numbers are in sectors, except num_clus 
  202.          * (which is in clusters)
  203.          */
  204.         tot_sectors = WORD(psect);
  205.         if(!tot_sectors) {
  206.             tot_sectors = DWORD(bigsect);            
  207.             nhs = DWORD(nhs);
  208.         } else
  209.             nhs = WORD(nhs);
  210.  
  211.         if(boot0.ext.old.dos4 == 0x29 && WORD(fatlen)) {
  212.             This->serialized = 1;
  213.             This->serial_number = DWORD(ext.old.serial);
  214.         }
  215.  
  216.         This->cluster_size = boot0.clsiz;         
  217.         This->fat_start = WORD(nrsvsect);
  218.         This->fat_len = WORD(fatlen);
  219.         This->dir_len = WORD(dirents) * MDIR_SIZE / This->sector_size;
  220.         This->num_fat = boot0.nfat;
  221.     }    
  222.     cylinder_size = dev.sectors * dev.heads;
  223.  
  224.     if(!mtools_skip_check && (tot_sectors % dev.sectors)){
  225.         fprintf(stderr,
  226.             "Total number of sectors not a multiple of"
  227.             " sectors per track!\n");
  228.         exit(1);
  229.     }
  230.  
  231.     /* full cylinder buffering */
  232. #ifdef FULL_CYL
  233.     disk_size = (dev.tracks) ? cylinder_size : 512;
  234. #else /* FULL_CYL */
  235.     disk_size = (dev.tracks) ? dev.sectors : 512;
  236. #endif /* FULL_CYL */
  237.  
  238. #if (defined sysv4 && !defined(solaris))
  239.     /*
  240.      * The driver in Dell's SVR4 v2.01 is unreliable with large writes.
  241.      */
  242.         disk_size = 0;
  243. #endif /* (defined sysv4 && !defined(solaris)) */
  244.  
  245. #ifdef linux
  246.     disk_size = cylinder_size;
  247. #endif
  248.  
  249. #if 1
  250.     if(disk_size > 256) {
  251.         disk_size = dev.sectors;
  252.         if(dev.sectors % 2)
  253.             disk_size <<= 1;
  254.     }
  255. #endif
  256.     if (disk_size % 2)
  257.         disk_size *= 2;
  258.  
  259.     if (disk_size)
  260.         This->Next = buf_init(This->Direct,
  261.                       disk_size * This->sector_size,
  262.                       This->sector_size,
  263.                       disk_size * This->sector_size);
  264.     else
  265.         This->Next = This->Direct;
  266.  
  267.     if (This->Next == NULL) {
  268.         perror("init: allocate buffer");
  269.         This->Next = This->Direct;
  270.     }
  271.  
  272.     /* read the FAT sectors */
  273.     if(fat_read(This, &boot0, dev.fat_bits, tot_sectors, dev.use_2m&0x7f)){
  274.         This->num_fat = 1;
  275.         FREE(&This->Next);
  276.         Free(This->Next);
  277.         return NULL;
  278.     }
  279.     return (Stream_t *) This;
  280. }
  281.