home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / MISC / GNU / SH164AS.ZIP / LIB / MS_DIO.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-28  |  20.9 KB  |  1,085 lines

  1. /* MS-DOS Direct Disk I/O
  2.  *
  3.  * MS-DOS Direct Disk I/O - Copyright (c) 1989 Data Logic Limited.
  4.  *
  5.  * dio_read and dio_write based on original code copyrighted (c) 1989
  6.  * Harold G. Walters.
  7.  *
  8.  * The rest of the code has been written from scatch to support multiple disk
  9.  * access and provide a consistant interface from normal I/O operations.
  10.  *
  11.  * The devices supported are:
  12.  *
  13.  *    /dev/hdxy    - Hard disk drive x parition y (x = 0 to 9, y =
  14.  *              0 to 9, where 0 is the whole disk) as a block
  15.  *              device
  16.  *    /dev/fdx    - Floppy drive x (x = 0 to 9) as a block device
  17.  *    /dev/rhdxy    - Hard disk drive as a character device
  18.  *    /dev/rfdx    - Floppy drive as a character device
  19.  *    /dev/kmem    - Memory driver
  20.  *
  21.  * It does its best to determine what type of disk you are reading.
  22.  *
  23.  * Redistribution and use in source and binary forms are permitted
  24.  * provided that the above copyright notice is duplicated in the
  25.  * source form.
  26.  *
  27.  * Version 1.2, 22 June 90
  28.  */
  29.  
  30. #include <sys/types.h>
  31. #include <sys/stat.h>
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <errno.h>
  36. #include <dos.h>
  37. #include <fcntl.h>
  38. #include <ctype.h>
  39. #include <unistd.h>
  40. #include <time.h>
  41. #include <stdarg.h>
  42. #include <ms_dio.h>
  43.  
  44. #undef open
  45. #undef close
  46. #undef read
  47. #undef write
  48. #undef lseek
  49. #undef fstat
  50. #undef stat
  51. #undef access
  52. #undef chmod
  53. #undef creat
  54. #undef dup
  55. #undef isatty
  56. #undef tell
  57.  
  58. #define SECSIZ        512        /* Sector size            */
  59. #define    MS_MODIFIER    30000
  60. #define BIOS_READ    0x2        /* BIOS functions        */
  61. #define BIOS_WRITE    0x3
  62. #define HD_FLAG        0x80        /* Hard disk flag        */
  63. #define MEGABYTE    1048576L
  64. #define DRIVE_RAM    20        /* RAM drive value        */
  65.  
  66. static int        dio_do (int, struct fs *, char *, long, unsigned int);
  67. static struct fs    *dio_fpcheck (int);
  68. static int        dio_fncheck (char *, mode_t *);
  69.  
  70. /* Our internal file handler table */
  71.  
  72. static struct fs {
  73.     int        mode;            /* Open mode            */
  74.     mode_t    st_mode;        /* File mode for stat        */
  75.     int        drive;
  76.     int        partition;        /* Hard disk partition number    */
  77.     off_t    location;        /* Current offset        */
  78.     long    m_start;        /* Offset for partition        */
  79.     long    m_cyl;            /* Max cylinders        */
  80.     int        m_head;            /* Max heads            */
  81.     int        m_sector;        /* Max sectors            */
  82.     long    m_scount;        /* Total sectors per disk    */
  83. } *MS_io_fs[_NFILE];
  84.  
  85. /* MSDOS Partition table */
  86.  
  87. struct partition {
  88.     long    f_type;            /* Type flags            */
  89.     long    f_status;        /* Status flags            */
  90.     long    offset;            /* Offset in sectors        */
  91.     long    size;            /* Size in sectors        */
  92. };
  93.  
  94. static int    fs_init = 0;        /* Initialisation complete    */
  95. static int    DIO_Error_Code;        /* Last do_dio Error Code    */
  96.  
  97. #define DEC_BADC    0x01        /* Bad command            */
  98. #define DEC_AMNF    0x02        /* Address mark not found    */
  99. #define DEC_WRITEP    0x03        /* Write protected        */
  100. #define DEC_SECNF    0x04        /* Sector not found        */
  101. #define DEC_RESET    0x05        /* Reset failed            */
  102. #define DEC_CHANGE    0x06        /* Diskette remove/changed    */
  103. #define DEC_PARAMETER    0x07        /* Bad parameter table        */
  104. #define DEC_DMAOVER    0x08        /* DMA overrun            */
  105. #define DEC_DMACROSS    0x09        /* DMA across 64K boundary    */
  106. #define DEC_BADSECTOR    0x0a        /* Bad sector detected        */
  107. #define DEC_BADTRACK    0x0b        /* Bad track detected        */
  108. #define DEC_UNSUPTRK    0x0c        /* Unsupported track        */
  109. #define DEC_INVSEC    0x0d        /* Invalid number of sectors    */
  110. #define DEC_CDAMD    0x0e        /* Control data address mark    */
  111. #define DEC_DMAARB    0x0f        /* DMA arbitration error    */
  112. #define DEC_CRC        0x10        /* bad CRC/ECC on read        */
  113. #define DEC_ECC        0x11        /* Data ECC corrected        */
  114. #define DEC_CONTROL    0x20        /* Controller failed        */
  115. #define DEC_SEEK    0x40        /* Seek failed            */
  116. #define DEC_TIMEOUT    0x80        /* Timeout            */
  117. #define DEC_NOTREADY    0xaa        /* Drive not ready        */
  118. #define DEC_UNDEF    0xbb        /* Undefined error        */
  119. #define DEC_WRITEF    0xcc        /* Write fault            */
  120. #define DEC_STATUS    0xe0        /* Status error            */
  121. #define DEC_SENSE    0xff        /* Sense operation failed    */
  122.  
  123. /* Do the actual read/write to the disk.  This function is not used
  124.  * for the RAM drive
  125.  */
  126.  
  127. static int    dio_do (type, FP, buf, secnum, secknt)
  128. int        type;
  129. struct fs    *FP;
  130. char        *buf;
  131. long        secnum;
  132. unsigned int    secknt;
  133. {
  134.     int            i, j;
  135.     int            nsec, cyl;
  136.     long        asec;
  137.     union REGS        reg;
  138. #if defined(M_I86LM)
  139.     struct SREGS    sreg;
  140. #endif
  141.  
  142.     DIO_Error_Code = 0;
  143.  
  144.     for (j = 0; j < secknt; j += nsec, buf += (nsec * SECSIZ), secnum += nsec)
  145.     {
  146.  
  147. /* Check for space - end of drive */
  148.  
  149.     if (secnum > FP->m_scount)
  150.     {
  151.         errno = ENOSPC;
  152.         return j * SECSIZ;
  153.     }
  154.  
  155. /* Calculate the number of sectors left on the track */
  156.  
  157.     asec = FP->m_start + secnum;
  158.  
  159.     if (((asec % FP->m_sector) + (secknt - j)) > FP->m_sector)
  160.         nsec = (int)(FP->m_sector - (asec % FP->m_sector));
  161.  
  162.     else
  163.         nsec = secknt - j;
  164.  
  165. /* Read/write it three times */
  166.  
  167.     for (i = 0; i < 3; i++)
  168.     {
  169.         reg.h.ah = (unsigned char)type;
  170.         reg.h.al = (unsigned char)nsec;
  171.         reg.h.dl = (unsigned char)FP->drive;
  172.  
  173.         cyl      = (int)(asec / (FP->m_head * FP->m_sector));
  174.         reg.h.cl = (unsigned char)((((asec % FP->m_sector) + 1) & 0x03f) |
  175.             ((cyl & 0x0300) >> 2));
  176.         reg.h.ch = (unsigned char)(cyl & 0xff);
  177.         reg.h.dh = (unsigned char)((asec % (FP->m_head * FP->m_sector)) / FP->m_sector);
  178.  
  179.  
  180. #if defined(M_I86LM)
  181.         reg.x.bx = FP_OFF(buf);
  182.         sreg.es = FP_SEG(buf);
  183.         int86x (0x13, ®, ®, &sreg);
  184. #else
  185.         reg.x.bx = (int) buf;
  186.         int86 (0x13, ®, ®);
  187. #endif
  188.  
  189.         if (!reg.x.cflag)
  190.         break;
  191.  
  192. /* If we are reading more than one sector - reduce the number of sectors by
  193.  * two
  194.  */
  195.  
  196.         else if (nsec > 1)
  197.         {
  198.         --i;
  199.         nsec /= 2;
  200.         }
  201.     }
  202.  
  203. /* Check for failure */
  204.  
  205.     if (i == 3)
  206.     {
  207.         DIO_Error_Code = (int)reg.h.ah;
  208.         errno = EIO;
  209.         return -1;
  210.     }
  211.     }
  212.  
  213.     return secknt * SECSIZ;
  214. }
  215.  
  216. /*
  217.  * write - Write function
  218.  */
  219.  
  220. int        dio_write (fp, from_buf, from_cnt)
  221. int        fp;            /* File handler            */
  222. char        *from_buf;        /* Output buffer        */
  223. unsigned int    from_cnt;        /* Number of bytes to write    */
  224. {
  225.     unsigned int    amt = 0;
  226.     unsigned int    err = 0;
  227.     long        fquo;
  228.     unsigned int    frem;
  229.     unsigned int    cquo = 0;
  230.     unsigned int    crem = 0;
  231.     struct fs        *FP;
  232.     char        buffer[SECSIZ];
  233.  
  234. /* Direct IO or normal */
  235.  
  236.     if (fp < MS_MODIFIER)
  237.     return write (fp, from_buf, from_cnt);
  238.  
  239.     if (((FP = dio_fpcheck (fp)) == (struct fs *)NULL) ||
  240.     ((FP->mode & 0x03) == O_RDONLY))
  241.     {
  242.     errno = EBADF;
  243.     return -1;
  244.     }
  245.  
  246. /* If RAM - just copy */
  247.  
  248.     if (FP->drive == DRIVE_RAM)
  249.     {
  250.     char huge     *cp = (char huge *)from_buf;
  251.     char huge     *sp = (char huge *)(((FP->location & 0x0ffff0L) << 12L)
  252.                         | (FP->location & 0x0fL));
  253.  
  254.     amt = from_cnt;
  255.     while (amt--)
  256.         *(sp++) = *(cp++);
  257.  
  258.     return from_cnt;
  259.     }
  260.  
  261. /* If the current location is not a sector boundary - read in the current
  262.  * sector and write a bit at the end to move to the boundary
  263.  */
  264.  
  265.     fquo = FP->location / SECSIZ;
  266.     frem = (unsigned int) (FP->location % SECSIZ);
  267.  
  268.     if (frem > 0)
  269.     {
  270.     if ((err = dio_do (BIOS_READ, FP, buffer, fquo, 1)) != SECSIZ)
  271.         return err;
  272.  
  273.     if ((amt = SECSIZ - frem) > from_cnt)
  274.         amt = from_cnt;
  275.  
  276. /* Update the buffer with the bit at the end */
  277.  
  278.     memcpy (&buffer[frem], from_buf, amt);
  279.  
  280.     if ((err = dio_do (BIOS_WRITE, FP, buffer, fquo, 1)) != SECSIZ)
  281.         return err;
  282.  
  283. /* Increment the location */
  284.  
  285.     FP->location += amt;
  286.  
  287.     if (SECSIZ - frem <= from_cnt)
  288.         fquo++;
  289.  
  290.     from_buf += amt;
  291.     from_cnt -= amt;
  292.     }
  293.  
  294. /* Calculate the number of full sectors to process now we are on a sector
  295.  * boundary
  296.  */
  297.  
  298.     cquo = from_cnt / SECSIZ;
  299.     crem = from_cnt % SECSIZ;
  300.  
  301.     if (cquo > 0)
  302.     {
  303.     if ((err = dio_do (BIOS_WRITE, FP, from_buf, fquo, cquo)) !=
  304.         (cquo * SECSIZ))
  305.     {
  306.         if (err > 0)
  307.         FP->location += err;
  308.  
  309.         return err;
  310.     }
  311.  
  312.     amt += (cquo * SECSIZ);
  313.     FP->location += (cquo * SECSIZ);
  314.     fquo += cquo;
  315.     from_buf += (cquo * SECSIZ);
  316.     from_cnt -= (cquo * SECSIZ);
  317.     }
  318.  
  319. /* Is there still more - read in the next sector, update first half and
  320.  * re-write
  321.  */
  322.  
  323.     if (crem > 0)
  324.     {
  325.     if ((err = dio_do (BIOS_READ, FP, buffer, fquo, 1)) != SECSIZ)
  326.         return err;
  327.  
  328.     memcpy (buffer, from_buf, crem);
  329.  
  330.     if ((err = dio_do (BIOS_WRITE, FP, buffer, fquo, 1)) != SECSIZ)
  331.         return err;
  332.  
  333.     amt += crem;
  334.     FP->location += crem;
  335.     }
  336.  
  337.     return amt;
  338. }
  339.  
  340. /*
  341.  * read - Read function
  342.  */
  343.  
  344. int        dio_read (fp, to_buf, to_cnt)
  345. int        fp;            /* File handler            */
  346. char        *to_buf;        /* Input buffer            */
  347. unsigned int    to_cnt;            /* Number of bytes to read    */
  348. {
  349.     unsigned int    amt = 0;
  350.     unsigned int    err = 0;
  351.     long        fquo;
  352.     unsigned int    frem;
  353.     unsigned int    cquo = 0;
  354.     unsigned int    crem = 0;
  355.     struct fs        *FP;
  356.     char        buffer[SECSIZ];
  357.  
  358. /* Direct IO or normal */
  359.  
  360.     if (fp < MS_MODIFIER)
  361.     return read (fp, to_buf, to_cnt);
  362.  
  363.     if (((FP = dio_fpcheck (fp)) == (struct fs *)NULL) ||
  364.     ((FP->mode & 0x03) == O_WRONLY))
  365.     {
  366.     errno = EBADF;
  367.     return -1;
  368.     }
  369.  
  370. /* If RAM - just copy */
  371.  
  372.     if (FP->drive == DRIVE_RAM)
  373.     {
  374.     char huge     *cp = (char huge *)to_buf;
  375.     char huge     *sp = (char huge *)(((FP->location & 0x0ffff0L) << 12L)
  376.                         | (FP->location & 0x0f));
  377.  
  378.  
  379.     amt = to_cnt;
  380.     while (amt--)
  381.         *(cp++) = *(sp++);
  382.  
  383.     return to_cnt;
  384.     }
  385.  
  386. /* Get the last part of the first sector required */
  387.  
  388.     fquo = FP->location / SECSIZ;
  389.     frem = (unsigned int) (FP->location % SECSIZ);
  390.  
  391.     if (frem > 0)
  392.     {
  393.     if ((err = dio_do (BIOS_READ, FP, buffer, fquo, 1)) != SECSIZ)
  394.         return err;
  395.  
  396.     if ((amt = SECSIZ - frem) > to_cnt)
  397.         amt = to_cnt;
  398.  
  399.     memcpy (to_buf, &buffer[frem], amt);
  400.  
  401.     FP->location += amt;
  402.     if (SECSIZ - frem <= to_cnt)
  403.         fquo++;
  404.  
  405.     to_buf += amt;
  406.     to_cnt -= amt;
  407.     }
  408.  
  409. /* Get the middle sectors required */
  410.  
  411.     cquo = to_cnt / SECSIZ;
  412.     crem = to_cnt % SECSIZ;
  413.  
  414.     if (cquo > 0)
  415.     {
  416.     if ((err = dio_do (BIOS_READ, FP, to_buf, fquo, cquo)) !=
  417.         (cquo * SECSIZ))
  418.     {
  419.         if (err > 0)
  420.         FP->location += err;
  421.  
  422.         return err;
  423.     }
  424.  
  425.     amt += (cquo * SECSIZ);
  426.     FP->location += (cquo * SECSIZ);
  427.     fquo += cquo;
  428.     to_buf += (cquo * SECSIZ);
  429.     to_cnt -= (cquo * SECSIZ);
  430.     }
  431.  
  432. /* Do we still need a partial sector ? */
  433.  
  434.     if (crem > 0)
  435.     {
  436.     if ((err = dio_do (BIOS_READ, FP, buffer, fquo, 1)) != SECSIZ)
  437.         return err;
  438.  
  439.     memcpy (to_buf, buffer, crem);
  440.     amt += crem;
  441.     FP->location += crem;
  442.     }
  443.  
  444.     return (amt);
  445. }
  446.  
  447. /*
  448.  * open - Open a file
  449.  */
  450.  
  451. int    dio_open (name, mode)
  452. char    *name;
  453. int    mode;
  454. {
  455.     struct fs    *FP;
  456.     int        fp, i, j;
  457.     int        drive, ndrive;
  458.     union REGS    iregs;
  459.     char    buf[SECSIZ];
  460.     va_list    ap;
  461.     int        permissions;
  462.     mode_t    dmode;
  463.  
  464. /* Check the permission mask if it exists */
  465.  
  466.     va_start (ap, mode);
  467.     permissions = va_arg (ap, int);
  468.     va_end (ap);
  469.  
  470. /* Check for initialisation */
  471.  
  472.     if (!(fs_init++))
  473.     memset (MS_io_fs, 0, sizeof (struct fs *) * _NFILE);
  474.  
  475. /* Direct I/o file name */
  476.  
  477.     if ((drive = dio_fncheck (name, &dmode)) != -1)
  478.     {
  479.     for (fp = 0; (fp < _NFILE) && (MS_io_fs[fp] != (struct fs *)NULL); fp++)
  480.         ;
  481.  
  482. /* Check for available entry and space */
  483.  
  484.     if ((fp == _NFILE) ||
  485.         ((FP = (struct fs *)malloc (sizeof (struct fs))) == (struct fs *)NULL))
  486.     {
  487.         errno = ENFILE;
  488.         return -1;
  489.     }
  490.  
  491.     FP->location = 0L;
  492.     FP->mode     = mode;
  493.     FP->st_mode  = dmode;
  494.  
  495. /* RAM access ? */
  496.  
  497.     if (drive == DRIVE_RAM)
  498.     {
  499.         FP->drive    = drive;
  500.         MS_io_fs[fp] = FP;
  501.         return fp + MS_MODIFIER;
  502.     }
  503.  
  504.     if (drive & HD_FLAG)
  505.     {
  506.         ndrive      = (drive & (~HD_FLAG));
  507.         FP->partition = ndrive % 10;
  508.         ndrive      /= 10;
  509.         FP->drive     = ndrive | HD_FLAG;
  510.         FP->m_start   = 0L;        /* Offset for partition        */
  511.     }
  512.  
  513.     else
  514.     {
  515.         FP->drive     = drive;
  516.         ndrive        = drive;
  517.         FP->partition = 0;
  518.         FP->m_start   = 0L;        /* Offset for partition        */
  519.     }
  520.  
  521.  
  522. /* Reset the drive */
  523.  
  524.     iregs.h.ah = 0;
  525.     iregs.h.dl = (unsigned char)FP->drive;
  526.     int86 (0x13, &iregs, &iregs);
  527.  
  528. /* Get the drive parameters */
  529.  
  530.     iregs.h.ah = 0x08;
  531.     iregs.h.dl = (unsigned char)FP->drive;
  532.     int86 (0x13, &iregs, &iregs);
  533.  
  534. /* Check for hard disk */
  535.  
  536.     if (FP->drive & HD_FLAG)
  537.     {
  538.         struct partition    *pp, tp;
  539.  
  540. /* System call failed - no device */
  541.  
  542.         if ((iregs.x.cflag) || (ndrive >= iregs.h.dl))
  543.         {
  544.         free (FP);
  545.         errno = ENOENT;
  546.         return -1;
  547.         }
  548.  
  549. /* OK - save the parameters */
  550.  
  551.         FP->m_cyl    = (iregs.h.ch | ((iregs.h.cl & 0x0c0) << 2)) + 2;
  552.         FP->m_head   = iregs.h.dh + 1;
  553.         FP->m_sector = iregs.h.cl & 0x03f;
  554.         FP->m_scount = FP->m_cyl * FP->m_head * FP->m_sector;
  555.  
  556. /* If this is not partition 0 - read the partition table */
  557.  
  558.         if (FP->partition)
  559.         {
  560.         if (dio_do (BIOS_READ, FP, buf, 0L, 1) == -1)
  561.         {
  562.             free (FP);
  563.             return -1;
  564.         }
  565.  
  566.         if (*(int *)&buf[510] != 0xaa55)
  567.         {
  568.             errno = ENOENT;
  569.             return -1;
  570.         }
  571.  
  572. /* Sort the partition table */
  573.  
  574.         pp = (struct partition *)&buf[0x1be];
  575.  
  576.         for (i = 0; i < 4; i++)
  577.         {
  578.             for (j = 0; j < 3; j++)
  579.             {
  580.             if (((!pp[j].offset) && pp[j + 1].offset) ||
  581.                 ((pp[j].offset > pp[j + 1].offset) &&
  582.                   pp[j + 1].offset))
  583.             {
  584.                 tp        = pp[j];
  585.                 pp[j]     = pp[j + 1];
  586.                 pp[j + 1] = tp;
  587.             }
  588.             }
  589.         }
  590.  
  591.         if (pp[FP->partition - 1].offset == 0L)
  592.         {
  593.             errno = ENOENT;
  594.             return -1;
  595.         }
  596.  
  597.         FP->m_start = pp[FP->partition - 1].offset;
  598.         FP->m_scount = pp[FP->partition - 1].size;
  599.         }
  600.     }
  601.  
  602. /* Floppy disk - get parameters.  We try our best here, but DOS 3.3 allows
  603.  * you to format any number of sectors per track and tracks per disk
  604.  */
  605.  
  606.     else
  607.     {
  608.  
  609. /* System call failed - think this means we're on an XT.  So set up the
  610.  * XT parameters
  611.  */
  612.  
  613.         if ((iregs.x.cflag) && (ndrive < 2))
  614.         {
  615.         iregs.h.bl   = 0x01;
  616.         FP->m_cyl    = 40;
  617.         FP->m_head   = 2;
  618.         FP->m_sector = 9;
  619.         }
  620.  
  621. /* No Drive */
  622.  
  623.         else if ((iregs.x.cflag) || (ndrive >= iregs.h.dl))
  624.         {
  625.         free (FP);
  626.         errno = ENOENT;
  627.         return -1;
  628.         }
  629.  
  630. /* OK - save the parameters */
  631.  
  632.         else
  633.         {
  634.         FP->m_cyl    = iregs.h.ch;
  635.         FP->m_head   = iregs.h.dh + 1;
  636.         FP->m_sector = iregs.h.cl;
  637.         }
  638.  
  639.         FP->m_scount = FP->m_cyl * FP->m_head * FP->m_sector;
  640.  
  641. /* High capacity drive ? */
  642.  
  643.         if ((iregs.h.bl == 0x02) || (iregs.h.bl == 0x03))
  644.         {
  645.  
  646. /* Try reading sector 0 */
  647.  
  648.         FP->m_sector = (iregs.h.bl == 0x02) ? 9 : 15;
  649.  
  650. /* If it failed - switch to the other type */
  651.  
  652.         if (dio_do (BIOS_READ, FP, buf, 0L, 1) == -1)
  653.         {
  654.  
  655. /* If not a sector not found error - abort */
  656.  
  657.             if ((DIO_Error_Code != DEC_SECNF) &&
  658.             (DIO_Error_Code != DEC_UNSUPTRK) &&
  659.             (DIO_Error_Code != DEC_INVSEC))
  660.             {
  661.             free (FP);
  662.             errno = EIO;
  663.             return -1;
  664.             }
  665.  
  666. /* Otherwise, switch type */
  667.  
  668.             FP->m_sector = (iregs.h.bl == 0x02) ? 15 : 9;
  669.  
  670.             iregs.h.ah   = 0x17;
  671.             iregs.h.dl   = (unsigned char)FP->drive;
  672.             iregs.h.al   = (unsigned char)(5 - iregs.h.bl);
  673.             int86 (0x13, &iregs, &iregs);
  674.         }
  675.         }
  676.  
  677. /* 8 or 9 Sectors, 1 or 2 heads */
  678.  
  679.         if (((iregs.h.bl > 0x00) || (iregs.h.bl < 0x04)) &&
  680.         (FP->m_sector == 9))
  681.         {
  682.         FP->m_scount = FP->m_cyl * FP->m_head * FP->m_sector;
  683.  
  684. /* Check to see if sector 8 exists */
  685.  
  686.         if (dio_do (BIOS_READ, FP, buf, 8L, 1) == -1)
  687.         {
  688.  
  689. /* If not a sector not found error - abort */
  690.  
  691.             if ((DIO_Error_Code != DEC_SECNF) &&
  692.             (DIO_Error_Code != DEC_UNSUPTRK) &&
  693.             (DIO_Error_Code != DEC_INVSEC))
  694.             {
  695.             free (FP);
  696.             errno = EIO;
  697.             return -1;
  698.             }
  699.  
  700.             FP->m_sector = 8;
  701.         }
  702.  
  703. /* Check to see if sector 380 exists */
  704.  
  705.         if (dio_do (BIOS_READ, FP, buf, 380L, 1) == -1)
  706.         {
  707.  
  708. /* If not a sector not found error - abort */
  709.  
  710.             if ((DIO_Error_Code != DEC_SECNF) &&
  711.             (DIO_Error_Code != DEC_UNSUPTRK) &&
  712.             (DIO_Error_Code != DEC_INVSEC))
  713.             {
  714.             free (FP);
  715.             errno = EIO;
  716.             return -1;
  717.             }
  718.  
  719.             FP->m_head = 1;
  720.         }
  721.         }
  722.  
  723. /* 720K drive - read sector 15 to see if 1.4M */
  724.  
  725.         else if (iregs.h.bl == 0x04)
  726.         {
  727.         FP->m_scount = FP->m_cyl * FP->m_head * FP->m_sector;
  728.  
  729.         if (dio_do (BIOS_READ, FP, buf, 17L, 1) == -1)
  730.         {
  731.  
  732. /* If not a sector not found error - abort */
  733.  
  734.             if ((DIO_Error_Code != DEC_SECNF) &&
  735.             (DIO_Error_Code != DEC_UNSUPTRK) &&
  736.             (DIO_Error_Code != DEC_INVSEC))
  737.             {
  738.             free (FP);
  739.             errno = EIO;
  740.             return -1;
  741.             }
  742.  
  743.             FP->m_sector = 9;
  744.         }
  745.         }
  746.  
  747.         FP->m_scount = FP->m_cyl * FP->m_head * FP->m_sector;
  748.     }
  749.  
  750. /* Set up the file descriptor entry and return the number */
  751.  
  752.     MS_io_fs[fp] = FP;
  753.     return fp + MS_MODIFIER;
  754.     }
  755.  
  756.     else
  757.     return open (name, mode, permissions);
  758. }
  759.  
  760. /* 
  761.  * fstat - fstat function
  762.  */
  763.  
  764. int        dio_fstat (fp, St)
  765. int        fp;
  766. struct stat    *St;
  767. {
  768.     struct fs        *FP;
  769.  
  770.     if (fp < MS_MODIFIER)
  771.     return fstat (fp, St);
  772.  
  773.     if ((FP = dio_fpcheck (fp)) == (struct fs *)NULL)
  774.     return -1;
  775.  
  776. /* Dummy values */
  777.  
  778.     memset (St, 0, sizeof (struct stat));
  779.     St->st_mode = FP->st_mode;
  780.     St->st_nlink = 1;
  781.  
  782.     if (FP->drive == DRIVE_RAM)
  783.     {
  784.     St->st_size = MEGABYTE;
  785.     St->st_rdev = 0x0300;
  786.     }
  787.  
  788.     else
  789.     {
  790.     St->st_rdev = ((FP->drive & (~HD_FLAG)) * 10 + FP->partition) |
  791.               ((FP->drive & HD_FLAG) ? 0x0200 : 0x0100);
  792.     St->st_dev = FP->drive;
  793.     }
  794.  
  795.     St->st_atime = time ((time_t *)NULL);
  796.     St->st_ctime = St->st_ctime;
  797.     St->st_mtime = St->st_atime;
  798.     return 0;
  799. }
  800.  
  801. /*
  802.  * close - Close function
  803.  */
  804.  
  805. int    dio_close (fp)
  806. int    fp;
  807. {
  808.     struct fs        *FP;
  809.  
  810.     if (fp < MS_MODIFIER)
  811.     return close (fp);
  812.  
  813.     if ((FP = dio_fpcheck (fp)) == (struct fs *)NULL)
  814.     return -1;
  815.  
  816.     free (FP);
  817.     MS_io_fs[fp - MS_MODIFIER] = (struct fs *)NULL;
  818.     return 0;
  819. }
  820.  
  821. /*
  822.  * lseek - Seek function
  823.  */
  824.  
  825. long    dio_lseek (fp, off, type)
  826. int    fp;
  827. off_t    off;
  828. int    type;
  829. {
  830.     off_t        check;
  831.     struct fs        *FP;
  832.  
  833.     if (fp < MS_MODIFIER)
  834.     return lseek (fp, off, type);
  835.  
  836.     if ((FP = dio_fpcheck (fp)) == (struct fs *)NULL)
  837.     return -1L;
  838.  
  839.     switch (type)
  840.     {
  841.     case SEEK_SET:
  842.         check = off;
  843.         break;
  844.  
  845.     case SEEK_CUR:
  846.         check = off + FP->location;
  847.         break;
  848.  
  849.     case SEEK_END:
  850.     default:
  851.         errno = EINVAL;
  852.         return -1L;
  853.     }
  854.  
  855.     if (check < 0L)
  856.     {
  857.     errno = EINVAL;
  858.     return -1L;
  859.     }
  860.  
  861.     return (FP->location = check);
  862. }
  863.  
  864. /*
  865.  * Check for a valid file pointer.  Look up the file handler in the table
  866.  * of our file handlers
  867.  */
  868.  
  869. static struct fs    *dio_fpcheck (fp)
  870. int            fp;
  871. {
  872.     struct fs    *FP;
  873.  
  874.     if (((FP = MS_io_fs[fp - MS_MODIFIER]) == (struct fs *)NULL) ||
  875.     (fp - MS_MODIFIER >= _NFILE) || (fp - MS_MODIFIER < 0))
  876.     {
  877.     errno = EBADF;
  878.     return (struct fs *)NULL;
  879.     }
  880.  
  881.     return FP;
  882. }
  883.  
  884. /*
  885.  * Check for a valid file name.  We are looking for one of 'our' file names
  886.  * /dev/hd??, /dev/fd? or /dev/mem.  The device number is returned.
  887.  */
  888.  
  889. static int    dio_fncheck (name, dmode)
  890. char        *name;
  891. mode_t        *dmode;
  892. {
  893.  
  894. /* Set up default mode */
  895.  
  896.     if (dmode != (mode_t *)NULL)
  897.     *dmode = 0x61b6;
  898.  
  899. /* Check for hard disk */
  900.  
  901.     if (isdigit (name[7]) && isdigit (name[8]) && (strlen (name) == 9) &&
  902.     (strnicmp (name, "/dev/hd", 7) == 0))
  903.     {
  904.     int    i = atoi (&name[7]);
  905.  
  906.     return ((i % 10) > 4) ? -1 : i | HD_FLAG;
  907.     }
  908.  
  909.     else if (isdigit (name[8]) && isdigit (name[9]) && (strlen (name) == 10) &&
  910.          (strnicmp (name, "/dev/rhd", 8) == 0))
  911.     {
  912.     int    i = atoi (&name[8]);
  913.  
  914.     if (dmode != (mode_t *)NULL)
  915.         *dmode = 0x21b6;
  916.  
  917.     return ((i % 10) > 4) ? -1 : i | HD_FLAG;
  918.     }
  919.  
  920. /* Check for floppy disk */
  921.  
  922.     else if (isdigit (name[7]) && (strlen (name) == 8) &&
  923.     (!strnicmp (name, "/dev/fd", 7)))
  924.     return name[7] - '0';
  925.  
  926.     else if (isdigit(name[8]) && (strlen (name) == 9) &&
  927.     (!strnicmp (name, "/dev/rfd", 8)))
  928.     {
  929.     if (dmode != (mode_t *)NULL)
  930.         *dmode = 0x21b6;
  931.  
  932.     return name[8] - '0';
  933.     }
  934.  
  935.     else if (!stricmp (name, "/dev/kmem"))
  936.     return DRIVE_RAM;
  937.  
  938.     return -1;
  939. }
  940.  
  941. /*
  942.  * stat - Get file status
  943.  */
  944.  
  945. int        dio_stat (name, St)
  946. char        *name;
  947. struct stat    *St;
  948. {
  949.     int        drive;
  950.     mode_t    dmode;
  951.  
  952.     if ((drive = dio_fncheck (name, &dmode)) == -1)
  953.     return stat (name, St);
  954.  
  955.     memset (St, 0, sizeof (struct stat));
  956.     St->st_mode  = dmode;
  957.     St->st_nlink = 1;
  958.     St->st_atime = time ((time_t *)NULL);
  959.     St->st_ctime = St->st_ctime;
  960.     St->st_mtime = St->st_atime;
  961.  
  962.     if (drive == DRIVE_RAM)
  963.     {
  964.     St->st_size = MEGABYTE;
  965.     St->st_rdev = 0x0300;
  966.     }
  967.  
  968.     else
  969.     {
  970.     St->st_rdev = (drive & (~HD_FLAG)) | ((drive & HD_FLAG) ? 0x0200
  971.                                 : 0x0100);
  972.     St->st_dev = drive;
  973.     }
  974.  
  975.     return 0;
  976. }
  977.  
  978. /*
  979.  * access - Check file access
  980.  */
  981.  
  982. int    dio_access (name, mode)
  983. char    *name;
  984. int    mode;
  985. {
  986.     if (dio_fncheck (name, (mode_t *)NULL) == -1)
  987.     return access (name, mode);
  988.  
  989.     else if (mode & 1)
  990.     {
  991.     errno = EACCES;
  992.     return -1;
  993.     }
  994.  
  995.     return 0;
  996. }
  997.  
  998. /*
  999.  * chmod - Change file permissions
  1000.  */
  1001.  
  1002. int    dio_chmod (name, mode)
  1003. char    *name;
  1004. int    mode;
  1005. {
  1006.     return (dio_fncheck (name, (mode_t *)NULL) == -1) ? chmod (name, mode) : 0;
  1007. }
  1008.  
  1009. /*
  1010.  * create - Create file
  1011.  */
  1012.  
  1013. int    dio_creat (name, mode)
  1014. char    *name;
  1015. int    mode;
  1016. {
  1017.     return (dio_fncheck (name, (mode_t *)NULL) == -1) ? creat (name, mode)
  1018.                       : dio_open (name, O_WRONLY, mode);
  1019. }
  1020.  
  1021. /*
  1022.  * dup - Duplicate handler
  1023.  */
  1024.  
  1025. int    dio_dup (fp)
  1026. int    fp;
  1027. {
  1028.     struct fs    *FP;        /* New pointer            */
  1029.     struct fs    *FP1;        /* Old pointer            */
  1030.  
  1031.     if (fp < MS_MODIFIER)
  1032.     return dup (fp);
  1033.  
  1034. /* Check valid */
  1035.  
  1036.     if ((FP1 = dio_fpcheck (fp)) == (struct fs *)NULL)
  1037.     return -1;
  1038.  
  1039. /* Create a new entry */
  1040.  
  1041.     for (fp = 0; (fp < _NFILE) && (MS_io_fs[fp] != (struct fs *)NULL); fp++)
  1042.     ;
  1043.  
  1044.     if ((fp == _NFILE) ||
  1045.     ((FP = (struct fs *)malloc (sizeof (struct fs))) == (struct fs *)NULL))
  1046.     {
  1047.     errno = EMFILE;
  1048.     return -1;
  1049.     }
  1050.  
  1051. /* Duplicate it */
  1052.  
  1053.     MS_io_fs[fp] = FP;
  1054.     *FP = *FP1;
  1055.     return fp;
  1056. }
  1057.  
  1058. /*
  1059.  * isatty - Check if tty
  1060.  */
  1061.  
  1062. int    dio_isatty (fp)
  1063. int    fp;
  1064. {
  1065.     if (fp < MS_MODIFIER)
  1066.     return isatty (fp);
  1067.  
  1068.     return 0;
  1069. }
  1070.  
  1071. /*
  1072.  * tell - Tell location
  1073.  */
  1074.  
  1075. long    dio_tell (fp)
  1076. int    fp;
  1077. {
  1078.     struct fs    *FP;
  1079.  
  1080.     if (fp < MS_MODIFIER)
  1081.     return tell (fp);
  1082.  
  1083.     return ((FP = dio_fpcheck (fp)) == (struct fs *)NULL) ? -1L : FP->location;
  1084. }
  1085.