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