EXTENDED FILE I/O LIBRARY








  PRODUCT  :  TURBO C                               NUMBER : 418
  VERSION  :  1.0/1.5
       OS  :  MS-DOS
     DATE  :  February 23, 1988                     PAGE  : 1/14

    TITLE  :  EXTENDED FILE I/O LIBRARY




  The following is public domain information that has been uploaded
  to  our Forum on CompuServe.  As a courtesy to our users that  do
  not  have  immediate  access  to  CompuServe,  Technical  Support
  distributes these routines free of charge.

  However,  because these routines are public domain programs,  not
  developed by Borland International,  we are unable to provide any
  technical support or assistance using these routines. If you need
  assistance   using   these   routines,    or   are   experiencing
  difficulties,  we  recommend  that you log  onto  CompuServe  and
  request  assistance  from the Forum members that developed  these
  routines.

  Written by
    Randy Forgaard,  CompuServe 70307,521

  Translated to Turbo C by
    Charles Jazdzewski

  Many   thanks   to  Bela  Lubkin, (CompuServe   76703,3015)   for
  masterminding   this   idea,   and  Kim   Kokkonen,   (CompuServe
  72457,2131)  for  helping me debug it.   For more  discussion  of
  Handle Tables and the implementation of DOS  redirection,  please
  see  Stan Mitchell,  "Command Line Redirection," PC Tech Journal,
  January 1986, Page 44.

  Due to a limitation of DOS,  Turbo  C, version 1.5 only allows up
  to 15 files at a time  to  be  open.  The following module allows
  you  to have up to 96 files open simultaneously under DOS 2.0  or
  2.1, or 252 files open simultaneously under DOS  3.0  or greater.
  This module, in its current form, CANNOT be used with streams nor
  networks.

  To use this module edit your CONFIG.SYS file (see the  DOS manual
  for details), so that it includes a line  that  says "FILES=XXX".
  XXX should be a version that is 3 greater than the maximum number
  files  you  wish  to  open,  and  should  not  exceed 99 (for DOS
  2.0/2.1) or 255 (for DOS 3.0 and higher). Under  any  version  of
  DOS, the minimum allowable value for XXX is 8. Then,  reboot your
  computer so that the FILES=XXX parameter takes hold.

  Running  the sample program at the bottom of this file will  tell
  you the maximum number of files you can open at once. (Usually 96













  PRODUCT  :  TURBO C                               NUMBER : 418
  VERSION  :  1.0/1.5
       OS  :  MS-DOS
     DATE  :  February 23, 1988                     PAGE  : 1/14

    TITLE  :  EXTENDED FILE I/O LIBRARY




  or  252,  unless  a resident program has opened  some  files  and
  they have not been closed).

  THE TECHNICAL DETAILS:

  Much  of the following information is not documented in  the  DOS
  Technical Reference manual.

  Under  DOS 1.0 and 1.1,  all files were accessed via File Control
  Blocks (FCB's).  There was no limit to the number of FCB's that a
  program could use,  so there was no limit to the number of  files
  open simultaneously.

  Under  DOS 2.0 and greater,  an alternate (and preferable) method
  of  accessing  files was introduced which uses a  2-byte  integer
  called  a  "handle"  to refer to a  file.   A  "handle"  file  is
  described  using  a data structure called a Device Control  Block
  (DCB).   However,  DOS provides the storage space for all  DCB's,
  rather  than having the application program store the  DCB's,  so
  the  number of available DCB's is limited to the amount of  space
  that  DOS  has  set  aside  for  them.   The  maximum  number  of
  files/devices  that can be open simultaneously is the  number  of
  slots  available in the DCB Table created by DOS.   The DCB's  in
  the DCB Table are consecutively numbered, starting with 0.  DCB's
  0,  1, and 2 are predefined by DOS to correspond to the AUX, CON,
  and  PRN devices,  respectively.   All remaining DCB's in the DCB
  Table  are  available for files or devices  used  by  application
  programs.

  So that I/O redirection can be supported, the DCB numbers are not
  used directly when accessing files.   Instead, a file "handle" is
  used.   A  "handle" is an index into a 20-byte array,  called the
  Handle  Table,  which  is  located at offset 18H of  the  Program
  Segment  Prefix (PSP) for a program (for a general discussion  of
  the PSP,  see the DOS Technical Reference manual).   Each element
  of the Handle Table is the DCB number of a file or  device.   The
  value  at index "handle" in the Handle Table is the DCB number of
  the file or device that implements that file  handle.   Thus,  if
  the  value 8 is in the 6th byte of the Handle Table,  the  handle
  "6" refers to the file (or device) described by the DCB in slot 8
  of the DCB Table.   If a handle is not currently being used,  its
  entry  in  the Handle Table is FFH.   DOS predefines the first  5
  handles to be primary input,  primary output,  error,  auxiliary,













  PRODUCT  :  TURBO C                               NUMBER : 418
  VERSION  :  1.0/1.5
       OS  :  MS-DOS
     DATE  :  February 23, 1988                     PAGE  : 1/14

    TITLE  :  EXTENDED FILE I/O LIBRARY




  and printer, so the first 5 entries in the Handle Table are 1, 1,
  1,  0,  and 2,  corresponding to the DCB numbers for the CON (1),
  AUX  (0),  and PRN (2) devices.   This leaves only  15  available
  handles for opening files (or new devices).

  Every time a new handle file is opened,  a new handle gets  used.
  Since there are only 20 slots available in the Handle Table for a
  program, DOS only allows a "process" to have a maximum of 20 file
  handles  in  use  simultaneously  (and the first  5  entries  are
  predefined,  as just noted,  unless those handles get closed  and
  reused).  Every new handle file requires a unique handle, so only
  20 files/devices can be open at the same time by a single process
  (unless  FCB's  are used).   (A "process" is any program  spawned
  using  the DOS EXEC function call.   A process can be invoked  by
  COMMAND.COM, or by another program.)  There can be many more than
  20 DCB's in the DCB Table,  so the real limitation is in the size
  of the Handle Table in the PSP.

  The  size  of  the  DCB  Table  (i.e.,   the  maximum  number  of
  files/devices  that  can  be open  simultaneously  in  the  whole
  computer)  is controlled by the FILES=XXX entry in the CONFIG.SYS
  file.   The minimum number of slots is 8.  Under DOS 2.0/2.1, the
  maximum number is 99,  and under DOS 3.0 and higher,  the maximum
  is 255.   As previously mentioned,  the first three of these  DCB
  slots are occupied by the AUX, CON, and PRN devices.

  A  single  program  can  use all of the DCB's in  the  DCB  Table
  (except for the 3 reserved by DOS) all on its own, by effectively
  bypassing  the  Handle Table in the PSP,  except on  a  temporary
  basis.   The program can accomplish this feat by using, say, only
  one entry in the Handle Table for all of its files.   Instead  of
  allowing  DOS to store the DCB numbers in the Handle  Table,  the
  program can store these numbers elsewhere.  Then, to manipulate a
  file using DOS, the program can temporarily put the DCB number of
  that  file into a designated slot in the Handle Table,  pass  the
  index  of that table slot (i.e.,  that "handle") to DOS,  and DOS
  will operate on that handle/DCB number.  In this way, DOS  can be
  fooled into accessing up   to 96 (or 252) different files/devices
  using a single  handle entry in the Handle Table.

  To obtain the address of the Handle Table, which is at offset 18H
  in  the PSP,  the program needs to find the address of  its  PSP.
  To do this we use  the  DOS  function  call  62H,    "Get Program













  PRODUCT  :  TURBO C                               NUMBER : 418
  VERSION  :  1.0/1.5
       OS  :  MS-DOS
     DATE  :  February 23, 1988                     PAGE  : 1/14

    TITLE  :  EXTENDED FILE I/O LIBRARY




  Segment Prefix  Address (PSP)."   This function call is available
  in DOS 3.0  and higher.   There is an  identical function call in
  DOS  2.0/2.1,  but its function number is 51H, and it   is    not
  documented.      Function 51H is also available  in  DOS 3.0/3.1.
  However,  for  upward-compatibility reasons with  future versions
  of DOS,   we  will  use  the  undocumented 51H function  with DOS
  2.0/2.1  (since we know 51H is available  in  those  versions  of
  DOS),  and  use  62H  for  DOS 3.0 and higher  (since  62H  is  a
  documented  function).   There  is no such function call  in  DOS
  1.0/1.1,  but the technique below will not work with those  early
  versions of DOS anyway,  since they did not provide file handles.

  /* EIO.C: Extended IO object module ----------------------------
   *    This module bypasses the normal 20 open file per-process
   *    limitation of DOS 2.0 and 3.0.  These routines are only
   *    limited by the number of files allotted for in the
   *    "FILES" statement in the config.sys file.
   * -------------------------------------------------------------
   */
  #include <stdio.h>
  #include <io.h>
  #include <dos.h>
  #include <process.h>

  #define UNUSEDHANDLE 0xFF

  /****************  Static Variables  ***************/
  /* HandleTable -------------------------------------
   *     Pointer to the program's file handle table
   *--------------------------------------------------
   */
  static unsigned char far *HandleTable = NULL;

  /* eioHandle ----------------------------------------
   *     The file handle that this package will use
   * --------------------------------------------------
   */
  static int eioHandle = 20;

  /****************  Internal Functions  ****************/

  /* GetHandleTableAddr() ------------------------------
   *   This function gets the process file handle table













  PRODUCT  :  TURBO C                               NUMBER : 418
  VERSION  :  1.0/1.5
       OS  :  MS-DOS
     DATE  :  February 23, 1988                     PAGE  : 1/14

    TITLE  :  EXTENDED FILE I/O LIBRARY




   *   location from DOS.
   * ---------------------------------------------------
   */
  static unsigned char far *GetHandleTableAddr(void)
  {
      union REGS regs;

      /* Determine which DOS function to use to get the PSP
       *   0x51 in 2.x (undocumented)
       *   0x62 in 3.x (documented)
       */
      switch( _osmajor )
      {
          case 0:
          case 1:
              fputs("This program only works with DOS 2.0 and"
                    " higher\n",stderr);
              exit(3);
          case 2:
              regs.h.ah = 0x51;
              break;
          default:
              regs.h.ah = 0x62;
              break;
      }

      int86(0x21,&regs,&regs);

      return (unsigned char far *) MK_FP(regs.x.bx, 0x18);
  }


  /************ Externally Assessable routines *************/

  /* eopen() ------------------------------------------------
   *    Opens a file and return its extended file handle.
   *    It replaces open().
   * --------------------------------------------------------
   */
  int eopen(char *pathname, int access, int permiss)
  {
       int handle;
       int SaveDcb;













  PRODUCT  :  TURBO C                               NUMBER : 418
  VERSION  :  1.0/1.5
       OS  :  MS-DOS
     DATE  :  February 23, 1988                     PAGE  : 1/14

    TITLE  :  EXTENDED FILE I/O LIBRARY




       /* Make sure we have the handle table's address */
       if ( !HandleTable )
           HandleTable = GetHandleTableAddr();

       /* Physically open the file */
       if ( (handle = open(pathname, access, permiss)) == -1 )
           return -1;

       /* Save the data control block */
       SaveDcb = HandleTable[handle];

       /* If we don't have a handle to play with, use this one,
        * else make it free again
        */
       if ( eioHandle > 19 )
           eioHandle = handle;
       else
           HandleTable[handle] = UNUSEDHANDLE;

       return SaveDcb;
  }

  /* eclose() --------------------------------------------------
   *    This routine replaces close().
   * -----------------------------------------------------------
   */
  int eclose(int handle)
  {
      HandleTable[eioHandle] = handle;
      return close(eioHandle);
  }

  /* eread() ---------------------------------------------------
   *    Replaces read().
   * -----------------------------------------------------------
   */
  int eread(int handle, void *buf, int nbyte)
  {
      HandleTable[eioHandle] = handle;
      return read(eioHandle, buf, nbyte);
  }

  /* ewrite() --------------------------------------------------













  PRODUCT  :  TURBO C                               NUMBER : 418
  VERSION  :  1.0/1.5
       OS  :  MS-DOS
     DATE  :  February 23, 1988                     PAGE  : 1/14

    TITLE  :  EXTENDED FILE I/O LIBRARY




   *    Replaces write().
   * -----------------------------------------------------------
   */
  int ewrite(int handle, void *buf, int nbyte)
  {
      HandleTable[eioHandle] = handle;
      return write(eioHandle, buf, nbyte);
  }

  /* elseek() --------------------------------------------------
   *    Replaces lseek().
   * -----------------------------------------------------------
   */
  long elseek(int handle, long offset, int fromwhere)
  {
      HandleTable[eioHandle] = handle;
      return lseek(eioHandle, offset, fromwhere);
  }
  /* ecreat() --------------------------------------------------
   *    Replaces creat().
   * -----------------------------------------------------------
   */
  int ecreat(char *filename, int permiss)
  {
       int handle;
       int SaveDcb;

       /* Make sure we have the handle table's address */
       if ( !HandleTable )
           HandleTable = GetHandleTableAddr();

       /* Physically open the file */
       if ( (handle = creat(filename, permiss)) == -1 )
           return -1;

       /* Save the data control block */
       SaveDcb = HandleTable[handle];

       /* If we don't have a handle to play with, use this one,
        * else make it free again
        */
       if ( eioHandle > 19 )
           eioHandle = handle;













  PRODUCT  :  TURBO C                               NUMBER : 418
  VERSION  :  1.0/1.5
       OS  :  MS-DOS
     DATE  :  February 23, 1988                     PAGE  : 1/14

    TITLE  :  EXTENDED FILE I/O LIBRARY




       else
           HandleTable[handle] = UNUSEDHANDLE;

       return SaveDcb;
  }

  /* ecreatnew() -----------------------------------------------
   *    Replaces creatnew().
   * -----------------------------------------------------------
   */
  int ecreatnew(char *filename, int attrib)
  {
       int handle;
       int SaveDcb;

       /* Make sure we have the handle table's address */
       if ( !HandleTable )
           HandleTable = GetHandleTableAddr();

       /* Physically open the file */
       if ( (handle = creatnew(filename, attrib)) == -1 )
           return -1;

       /* Save the data control block */
       SaveDcb = HandleTable[handle];

       /* If we don't have a handle to play with, use this one,
        * else make it free again
        */
       if ( eioHandle > 19 )
           eioHandle = handle;
       else
           HandleTable[handle] = UNUSEDHANDLE;

       return SaveDcb;
  }

  /* ecreattemp() ----------------------------------------------
   *    Replaces creattemp().
   * -----------------------------------------------------------
   */
  int ecreattemp(char *filename, int attrib)
  {













  PRODUCT  :  TURBO C                               NUMBER : 418
  VERSION  :  1.0/1.5
       OS  :  MS-DOS
     DATE  :  February 23, 1988                     PAGE  : 1/14

    TITLE  :  EXTENDED FILE I/O LIBRARY




       int handle;
       int SaveDcb;

       /* Make sure we have the handle table's address */
       if ( !HandleTable )
           HandleTable = GetHandleTableAddr();

       /* Physically open the file */
       if ( (handle = creattemp(filename, attrib)) == -1 )
           return -1;

       /* Save the data control block */
       SaveDcb = HandleTable[handle];

       /* If we don't have a handle to play with, use this one,
        * else make it free again
        */
       if ( eioHandle > 19 )
           eioHandle = handle;
       else
           HandleTable[handle] = UNUSEDHANDLE;

       return SaveDcb;
  }

  /* eeof() ----------------------------------------------------
   *    Replaces eeof().
   * -----------------------------------------------------------
   */
  int eeof(int handle)
  {
      HandleTable[eioHandle] = handle;
      return eof(eioHandle);
  }

  /* efilelength() --------------------------------------------
   *     Replaces filelength().
   * ----------------------------------------------------------
   */
  long efilelength(int handle)
  {
      HandleTable[eioHandle] = handle;
      return filelength(eioHandle);













  PRODUCT  :  TURBO C                               NUMBER : 418
  VERSION  :  1.0/1.5
       OS  :  MS-DOS
     DATE  :  February 23, 1988                     PAGE  : 1/14

    TITLE  :  EXTENDED FILE I/O LIBRARY




  }

  /* egetftime() ----------------------------------------------
   *     Replaces getftime().
   * ----------------------------------------------------------
   */
  int egetftime(int handle, struct ftime *ftimep)
  {

      HandleTable[eioHandle] = handle;
      return getftime(eioHandle, ftimep);
  }

  /* esetftime() ---------------------------------------------
   *     Replaces setftime().
   * ---------------------------------------------------------
   */
  int esetftime(int handle, struct ftime *ftimep)
  {
      HandleTable[eioHandle] = handle;
      return setftime(eioHandle, ftimep);
  }

  /* eioctl() -----------------------------------------------
   *    Replace ioctl().
   * --------------------------------------------------------
   */
  int eioctl(int handle, int cmd, int *argdx, int argcx)
  {
      HandleTable[eioHandle] = handle;
      return ioctl(eioHandle, cmd, argdx, argcx);
  }

  /* eisatty() ---------------------------------------------
   *    Replaces isatty().
   * -------------------------------------------------------
   */
  int eisatty(int handle)
  {
      HandleTable[eioHandle] = handle;
      return isatty(eioHandle);
  }














  PRODUCT  :  TURBO C                               NUMBER : 418
  VERSION  :  1.0/1.5
       OS  :  MS-DOS
     DATE  :  February 23, 1988                     PAGE  : 1/14

    TITLE  :  EXTENDED FILE I/O LIBRARY




  /* esetmode() --------------------------------------------
   *    Replaces setmode().
   * -------------------------------------------------------
   */
  int esetmode(int handle, unsigned mode)
  {

      HandleTable[eioHandle] = handle;
      return setmode(eioHandle, mode);
  }

  /* etell() -----------------------------------------------
   *     Replaces tell().
   * -------------------------------------------------------
   */
  long etell(int handle)
  {
      HandleTable[eioHandle] = handle;
      return tell(eioHandle);
  }


  /*----------------------------------------------------------
   * EIO.H: Header file for the extended file system
   *        This file should be include in any program
   *        using the EIO module.
   *----------------------------------------------------------
   */

  #include <io.h>

  int  eopen(char *pathname, int access, ... );
  int  eclose(int handle);
  int  eread(int handle, void *buf, int nbyte);
  int  ewrite(int handle, void *buf, int nbytes);
  long elseek(int handle, long offset, int fromwhere);
  int  ecreat(char *filename, int permiss);
  int  ecreatnew(char *filename, int attrib);
  int  ecreattemp(char *filename, int attrib);
  int  eeof(int handle);
  long efilelength(int handle);
  int  egetftime(int handle, struct ftime *ftimep);
  int  esetftime(int handle, struct ftime *ftimep);













  PRODUCT  :  TURBO C                               NUMBER : 418
  VERSION  :  1.0/1.5
       OS  :  MS-DOS
     DATE  :  February 23, 1988                     PAGE  : 1/14

    TITLE  :  EXTENDED FILE I/O LIBRARY




  int  eioctl(int handle, int cmd, ... );
  int  eisatty(int handle);
  int  esetmode(int handle, unsigned mode);
  long etell(int handle);

  /* Example  program -- This  program  opens as many Text files as
  it can,    until   DOS  runs out of room in its  DCB  Table.   It
  then reports how many  files  were  successfully opened, writes a
  line  to  each  of them,  then closes and erases  each  of  them.
  Note:  The value  of the FILES=XXX parameter  in  the  CONFIG.SYS
  file  must   be set  to  an appropriate value (see above).     If
  you    change  the FILES=XXX value,  be  sure  to  reboot  before
  running this program.

  This program takes a while to run,  due to the heavy disk I/O, so
  running  it  on  a hard disk (or,  even better,  a RAM  disk)  is
  recommended.   Make  sure that you are running the program  in  a
  subdirectory,  so  that you don't run up against the DOS limit on
  the number of allowable files in the root directory of a drive.
  */

  #include <stdio.h>
  #include <string.h>
  #include <fcntl.h>
  #include <dos.h>
  #include <process.h>
  #include "eio.h"

  #define MAXCOUNT 255

  int eiofiles[MAXCOUNT];
  char filename[MAXCOUNT][30];

  int main(void)
  {
      int i;
      int count;

      printf("Opening file...\n");
      for( i=0;  ;i++)
      {
           strcpy(filename[i],".\\");
           if ( (eiofiles[i] = ecreattemp(filename[i],0)) == -1)













  PRODUCT  :  TURBO C                               NUMBER : 418
  VERSION  :  1.0/1.5
       OS  :  MS-DOS
     DATE  :  February 23, 1988                     PAGE  : 1/14

    TITLE  :  EXTENDED FILE I/O LIBRARY




               break;
           printf("%s opened\n",filename[i]);
      }

      count = i;

      printf("Successfully opened %d files at the same time.\n"
             "Writing to each file...\n", count);

      for (i=0; i<count; i++)
          if ( ewrite(eiofiles[i],"This is a test",
               strlen("This is a test"))
               == 0)
          {
              perror("ewrite");
              return 1;
          }

      printf("Closing and erasing each file....\n");
      for (i=0; i<count; i++)
      {
          eclose(eiofiles[i]);
          unlink(filename[i]);
      }

      return 0;
  }


  The following is the project file that can be used to compile the
  above program:

  eio.c
  testeio.c















Comments

Popular posts from this blog

BOTTOM LIVE script

Fawlty Towers script for "A Touch of Class"