[comp.os.msdos.programmer] How to change Number of Open Files

chu@pioneer.arc.nasa.gov (Susie Chu RCS) (03/31/91)

Can someone tell me how to change the number of files that can 
be open simutaaneously?
My system is runing MSDOS 4.1 and I am using Turbo C 2.0.
I have a program that needs to open more than 20 files. I
have tried to
(1) in config.sys, change FILES=35
(2) in Turbo C 2.0 include/stdio.h, change
    #define OPEN_MAX  35
    #define SYS_OPEN 355
(3) in Turbo C 2.0 include/dos.h, change
    #define NFDS 35
It doesn't help.  I still failed in openning 21st file.  I suspect
it is in the libc.  But I don't know how to check and modify it.

If you do know, please tell me.  I will appreciate very much.
Thanks in advance.
---Susie Chu

net address: chu@pioneer.arc.nasa.gov
UUCP: {ihnp4,ucbvax,nike,lll-crg}!ames!pioneer!chu
Disclaimer: NASA is in no way responsible for the content of the previous mes-
    sag I take full and sole responsibility.

tabu6@CCVAX.IASTATE.EDU (Adam Goldberg) (04/01/91)

In article <1991Mar31.011139.8147@news.arc.nasa.gov>, chu@pioneer.arc.nasa.gov (Susie Chu RCS) writes:
>Can someone tell me how to change the number of files that can 
>be open simutaaneously?
>My system is runing MSDOS 4.1 and I am using Turbo C 2.0.
>I have a program that needs to open more than 20 files. I
>have tried to
>(1) in config.sys, change FILES=35
>(2) in Turbo C 2.0 include/stdio.h, change
>    #define OPEN_MAX  35
>    #define SYS_OPEN 355
>(3) in Turbo C 2.0 include/dos.h, change
>    #define NFDS 35
>It doesn't help.  I still failed in openning 21st file.  I suspect

Try adding to config.sys the line:
   BUFFERS=35
(though that'll eat up RAM, it seems likely that you don't have enough
buffers).

+----------------------------------------------------------------------------+
+ Adam Goldberg                         Bitnet:   tabu6@ISUVAX.BITNET        +
+ Iowa State University                 Internet: tabu6@CCVAX.IASTATE.EDU    +
+          "It's simple!  Even a Pascal programmer could do it!"             +
+ "Remember: The sooner you fall behind, the more time you have to catch up" +
+----------------------------------------------------------------------------+

bwilliam%peruvian.utah.edu@cs.utah.edu (Bruce R. Williams) (04/01/91)

In article <1991Mar31.213543.28347@news.iastate.edu> tabu6@CCVAX.IASTATE.EDU writes:
>In article <1991Mar31.011139.8147@news.arc.nasa.gov>, chu@pioneer.arc.nasa.gov (Susie Chu RCS) writes:
>>Can someone tell me how to change the number of files that can 
>>be open simutaaneously?
>>My system is runing MSDOS 4.1 and I am using Turbo C 2.0.
>>I have a program that needs to open more than 20 files. I
>>have tried to
>>(1) in config.sys, change FILES=35
   [...]
>
>Try adding to config.sys the line:
>   BUFFERS=35
>(though that'll eat up RAM, it seems likely that you don't have enough
>buffers).


Hi!  I think I can help with this...  

It isn't a matter of how many buffers you have, it's a limit set inside DOS.
You're not stuck though...

With MS-DOS Versions 3.3 and later, there is a DOS function (int 21h,
function 67h), which allows you to specify the max. number of files that
may be open at one time.  Previous versions of DOS were limited to at most
20.

Since you are using MS-DOS 4.01 this will work.  If you need to write code
that is compatable with older versions, there is a work-around that involves
using your own table of file handles instead of DOS's.  See "MS-DOS Advanced
Programming" by Michael J. Young for a good example.

To use the DOS function:

  Set AH to 67h,
  Set BX to the new max number of file handles.
  Call Int 21h

  Upon return, if CF is 1 then there was an error and
  the error code is stored in AX.

Using Turbo C, this can all be done either by using inline assembly, or 
by using one of the C functions for calling interrupts: intdos, int86,
intr etc.

Good Luck!  I hope this was clear -- otherwise feel free to e-mail.


-Bruce

Bruce R. Williams                "The most beautiful thing we can experience
University of Utah                is the mysterious.  It is the source of all
(bwilliam@peruvian.utah.edu)      true art and science."  -Albert Einstein

raymond@math.berkeley.edu (Raymond Chen) (04/02/91)

In article <1991Apr1.023910.22196@hellgate.utah.edu>, bwilliam%peruvian (Bruce R. Williams) writes:
>It isn't a matter of how many buffers you have, it's a limit set inside DOS.

Actually, it's a limit that Borland stupidly hard-coded into their
library support routines.  If you study the library source code,
you'll see a line that says

	#define NFILES 20

and then external arrays _openfd and _iobuf declared to be NFILES
elements long.  (I may have the array names wrong; I'm working
from memory.)  The number twenty is HARD-CODED into all of the
I/O support routines (fopen, read, seek, etc.), so the only way
to get around the limit is either

[1] Buy the TC source code, change the #define and recompile.
[2] Reverse-engineer the library object code and change the 20 to
    a larger number in all of the functions where it appears,
    as well as deleting the OBJs that declare _iobuf and _openfd
    and adding replacements that declare them with a larger size.
[3] Avoid the supplied functions and talk to DOS directly.
[4] Switch to a different compiler.  (MSC comes with instructions
    in one of its README files on how to increase the number
    of open files.)

I can probably help anyone who wants to try method [2].

dwayne@stratsft.UUCP (Dwayne Bailey) (04/02/91)

In article <1991Mar31.011139.8147@news.arc.nasa.gov> chu@pioneer.arc.nasa.gov (Susie Chu RCS) writes:
>Can someone tell me how to change the number of files that can 
>be open simutaaneously?
>My system is runing MSDOS 4.1 and I am using Turbo C 2.0.
>I have a program that needs to open more than 20 files. I
>have tried to
>(1) in config.sys, change FILES=35
>(2) in Turbo C 2.0 include/stdio.h, change
>    #define OPEN_MAX  35
>    #define SYS_OPEN 355
>(3) in Turbo C 2.0 include/dos.h, change
>    #define NFDS 35
>It doesn't help.  I still failed in openning 21st file.  I suspect
>it is in the libc.  But I don't know how to check and modify it.
>
>If you do know, please tell me.  I will appreciate very much.
>Thanks in advance.
>---Susie Chu
>

Two things are probably biting you.  One is that MS-DOS gives each and
every process EXACTLY 20 file handles at startup, no matter what is in
CONFIG.SYS.  The FILES= line controls the TOTAL number of files open, not
the number of files for one process.  Thus, your TSRs can have files open
without interfering with the 20 file handles of your main program.

The other problem is that thos #defines you changed had very little effect,
if any.  They tell your program the size of some external arrays.  You lied
to your program about those arrays, BUT YOU DIDN'T ACTUALLY CHANGE THEIR
SIZE!  To do that, you would need access to the source code for the Runtime
Library, and recompile with your changes.

There are workarounds.  The DOS limit is easy, since you are using 4.0
This code will only work in DOS 3.3 and higher.

/* Routine to set the maximum handles allowed to other than 20 */
/* Returns 0 on success, DOS Error number on failure */

int SetHandleLimit(int MaxHandles)
{
	int Result = 0;

	asm
		{
		mov	ah,67h	; This might need to be 0x67.  I can't
				; remember which style HEX number TC
				; wants here.
		mov	bx,MaxHandles
		int	21h	; Ditto the above comment

		jnc	NoError

		mov	Result,ax
NoError:
		}

	return Result;
}

Add a line like "SetHandleLimit(25);" to increase the limit to 35.  The only
reason this should fail is if there is not enough memory for DOS to allocate
a 35 byte table for the new handles.

BTW, this can be dome is versions of DOS below 3.3, but it's ugly.  There is
no function to do it for you.  You have to allocate the table youself, then
set the far pointer to the table in you PSP at offset 34h.  The word at
32h must also be set to the number of entries on the new table.

Now for Turbo C:
If you don't need stream IO (FILE * type files), then
you can get around the Runtime library by using just the low-level calls.
I would use _dos_open() to open the files, rather than open(), just to be
sure you are at a low enough level to get past the runtime library.

If you DO need stream IO, you might be able to do the same thing.  You would
just need some extra steps.  Be warned, this paragraph is total conjecture
on my part.  I have not tried is, and make no warranties, expressed or
implied!  That said, the following MIGHT work:
	1.  Open the file(s) using _dos_open().
	2.  Use fdopen() to associate the file handle with a stream.
	3.  Process the file as before.
	4.  Close the file.
This doesn't give you more than 20 streams at one time, but as long as you
aren't swapping back and forth between files TOO much, the performance hit
shouldn't be too bad.  You could also try using a call to dup() to make a
copy of the file handle after set 1.  That way, the close in step 4 will not
close the file completely, just remove its association with the stream 
pointer.  If this works, I suspect it will meet your needs the best.
However, I still recomment that, if at all possible, use only low level
calls, and avoid a ton of headaches.  Or buy the Runtime Library source.
The money spent will most likely be saved in time and aggravation!

========================================================================
..!uunet!basfpac!stratsft!dwayne

Dwayne Bailey      +  Strategic Software is ME, so my opinions ARE those
Strategic Software +  of my company!
========================================================================