home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume11 / mtools / part01 / init.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-08-27  |  5.8 KB  |  283 lines

  1. /*
  2.  * Initialize a MSDOS diskette.  Get the media signature (1st FAT entry)
  3.  * and switch to the proper floppy disk device to match the format
  4.  * of the disk.  Sets a bunch of global variables.  Returns 0 on success,
  5.  * or 1 on failure.
  6.  */
  7.  
  8. #include <stdio.h>
  9. #include <ctype.h>
  10. #include "msdos.h"
  11.  
  12. extern int fd, dir_len, dir_start, clus_size, fat_len, num_clus;
  13. extern unsigned char *fatbuf;
  14. extern char *mcwd;
  15.  
  16. int
  17. init(mode)
  18. int mode;
  19. {
  20.     int code = 0, buflen;
  21.     unsigned char read_fat(), fat;
  22.     char *getenv(), *fixmcwd(), *malloc(), version, get_dos_ver();
  23.     long lseek();
  24.     void perror(), exit();
  25.  
  26.                     /* open the 'generic' floppy */
  27.     if ((fd = open(FLOPPY, mode)) < 0) {
  28.         perror("init: open");
  29.         exit(1);
  30.     }
  31.                     /* read media signature (1st FAT) */
  32.     fat = read_fat();
  33.     switch(fat) {
  34.         case 0xfe:
  35. #ifndef FLP_40_8_1
  36.             fprintf(stderr, "40 track, 8 sector, single sided: not supported\n");
  37.             code = 1;
  38. #else FLP_40_8_1
  39.             dir_start = 3;
  40.             dir_len = 4;
  41.             clus_size = 1;
  42.             fat_len = 1;
  43.             num_clus = 313;
  44.             close(fd);
  45.             if ((fd = open(FLP_40_8_1, mode)) < 0) {
  46.                 perror("init: open");
  47.                 return(1);
  48.             }
  49. #endif FLP_40_8_1
  50.             break;
  51.         case 0xff:
  52. #ifndef FLP_40_8_2
  53.             fprintf(stderr, "40 track, 8 sector, double sided: not supported\n");
  54.             code = 1;
  55. #else FLP_40_8_2
  56.             dir_start = 3;
  57.             dir_len = 7;
  58.             clus_size = 2;
  59.             fat_len = 1;
  60.             num_clus = 315;
  61.             close(fd);
  62.             if ((fd = open(FLP_40_8_2, mode)) < 0) {
  63.                 perror("init: open");
  64.                 return(1);
  65.             }
  66. #endif FLP_40_8_2
  67.             break;
  68.         case 0xfc:
  69. #ifndef FLP_40_9_1
  70.             fprintf(stderr, "40 track, 9 sector, single sided: not supported\n");
  71.             code = 1;
  72. #else FLP_40_9_1
  73.             dir_start = 5;
  74.             dir_len = 4;
  75.             clus_size = 1;
  76.             fat_len = 2;
  77.             num_clus = 351;
  78.             close(fd);
  79.             if ((fd = open(FLP_40_9_1, mode)) < 0) {
  80.                 perror("init: open");
  81.                 return(1);
  82.             }
  83. #endif FLP_40_9_1
  84.             break;
  85.         case 0xfd:
  86. #ifndef FLP_40_9_2
  87.             fprintf(stderr, "40 track, 9 sector, double sided: not supported\n");
  88.             code = 1;
  89. #else FLP_40_9_2
  90.             dir_start = 5;
  91.             dir_len = 7;
  92.             clus_size = 2;
  93.             fat_len = 2;
  94.             num_clus = 354;
  95.             close(fd);
  96.             if ((fd = open(FLP_40_9_2, mode)) < 0) {
  97.                 perror("init: open");
  98.                 return(1);
  99.             }
  100. #endif FLP_40_9_2
  101.             break;
  102.         case 0xf9:        /* all 80 track disks */
  103.             version = get_dos_ver();
  104.             switch (version) {
  105.                 case '0':
  106.                 case '1':
  107. #ifndef FLP_80_15_2
  108.                     fprintf(stderr, "80 track, 15 sector, double sided: not supported\n");
  109.                     code = 1;
  110. #else FLP_80_15_2
  111.                     dir_start = 15;
  112.                     dir_len = 14;
  113.                     clus_size = 1;
  114.                     fat_len = 7;
  115.                     num_clus = 1193;
  116.                     close(fd);
  117.                     if ((fd = open(FLP_80_15_2, mode)) < 0) {
  118.                         perror("init: open");
  119.                         return(1);
  120.                     }
  121. #endif FLP_80_15_2
  122.                     break;
  123.                 case '2':
  124. #ifndef FLP_80_9_2
  125.                     fprintf(stderr, "3.5 inch 80 track, 9 sector, double sided: not supported\n");
  126.                     code = 1;
  127. #else FLP_80_9_2
  128.                     dir_start = 7;
  129.                     dir_len = 7;
  130.                     clus_size = 2;
  131.                     fat_len = 3;
  132.                     num_clus = 713;
  133.                     close(fd);
  134.                     if ((fd = open(FLP_80_9_2, mode)) < 0) {
  135.                         perror("init: open");
  136.                         return(1);
  137.                     }
  138. #endif FLP_80_9_2
  139.                     break;
  140.                 default:
  141.                     fprintf(stderr, "Unknown DOS version '%02x'\n", version);
  142.                     code = 1;
  143.                     break;
  144.             }
  145.             break;
  146.         default:
  147.             fprintf(stderr, "Unknown format '%02x'\n", fat);
  148.             code = 1;
  149.             break;
  150.     }
  151.     if (code)
  152.         return(1);
  153.  
  154.     buflen = fat_len * MSECSIZ;
  155.     fatbuf = (unsigned char *) malloc(buflen);
  156.     move(1);
  157.                     /* read the FAT sectors */
  158.     if (read(fd, fatbuf, buflen) != buflen) {
  159.         perror("init: read");
  160.         exit(1);
  161.     }
  162.                     /* set dir_chain to root directory */
  163.     reset_dir();
  164.                     /* get Current Working Directory */
  165.     mcwd = fixmcwd(getenv("MCWD"));
  166.                     /* test it out.. */
  167.     if (subdir("")) {
  168.         fprintf(stderr, "Environmental variable MCWD needs updating\n");
  169.         exit(1);
  170.     }
  171.     return(0);
  172. }
  173.  
  174. /*
  175.  * Move the read/write head to the next location.  Tries to optimize
  176.  * the movement by moving relative to current location.  The argument
  177.  * is a logical sector number.  All errors are fatal.
  178.  */
  179.  
  180. move(sector)
  181. int sector;
  182. {
  183.     long cur_loc, next, lseek();
  184.     void exit(), perror();
  185.                     /* get current location */
  186.     if ((cur_loc = lseek(fd, 0L, 1)) < 0) {
  187.         perror("move: lseek");
  188.         exit(1);
  189.     }
  190.     next = (long) (MSECSIZ * sector) - cur_loc;
  191.                     /* we're already there */
  192.     if (next == 0L)
  193.         return;
  194.                     /* move to next location */
  195.     if (lseek(fd, next, 1) < 0) {
  196.         perror("move: lseek");
  197.         exit(1);
  198.     }
  199.     return;
  200. }
  201.  
  202. /*
  203.  * Fix MCWD to be a proper directory name.  Always has a leading separator.
  204.  * Never has a trailing separator (unless it is the path itself).
  205.  */
  206.  
  207. char *
  208. fixmcwd(dirname)
  209. char *dirname;
  210. {
  211.     char *s, *malloc(), *strcpy(), *strcat();
  212.     static char *ans;
  213.  
  214.     ans = malloc(strlen(dirname)+2);
  215.                     /* add a leading separator */
  216.     if (*dirname != '/' && *dirname != '\\') {
  217.         strcpy(ans, "/");
  218.         strcat(ans, dirname);
  219.     }
  220.     else
  221.         strcpy(ans, dirname);
  222.                     /* translate to upper case */
  223.     for (s = ans; *s; ++s) {
  224.         if (islower(*s))
  225.             *s = toupper(*s);
  226.     }
  227.                     /* if separator alone */
  228.     if (strlen(ans) == 1)
  229.         return(ans);
  230.                     /* zap the trailing separator */
  231.     s--;
  232.     if (*s == '/' || *s == '\\')
  233.         *s = NULL;
  234.     return(ans);
  235. }
  236.  
  237. /*
  238.  * Read the first byte of the FAT table.  This code serves as a media
  239.  * signature for the diskette.
  240.  */
  241.  
  242. unsigned char
  243. read_fat()
  244. {
  245.     unsigned char buf[MSECSIZ];
  246.     static unsigned char ans;
  247.                     /* move to boot sector */
  248.     if (lseek(fd, (long) MSECSIZ, 0) < 0) {
  249.         perror("init: lseek");
  250.         exit(1);
  251.     }
  252.                     /* read the first FAT sector */
  253.     if (read(fd, buf, MSECSIZ) != MSECSIZ) {
  254.         perror("init: read");
  255.         exit(1);
  256.     }
  257.     ans = *buf;
  258.     return(ans);
  259. }
  260.  
  261. /*
  262.  * Read the Boot Sector to figure out the DOS version.
  263.  */
  264.  
  265. char
  266. get_dos_ver()
  267. {
  268.     unsigned char bootbuf[MSECSIZ];
  269.     static char ans;
  270.                     /* move to boot sector */
  271.     if (lseek(fd, 0L, 0) < 0) {
  272.         perror("init: lseek");
  273.         exit(1);
  274.     }
  275.                     /* read the boot sector */
  276.     if (read(fd, bootbuf, MSECSIZ) != MSECSIZ) {
  277.         perror("init: read");
  278.         exit(1);
  279.     }
  280.     ans = *(bootbuf+10);
  281.     return(ans);
  282. }
  283.