Date: Tue, 18 Mar 1997 14:15:04 +0300 (IDT) From: Eli Zaretskii To: Delong cc: djgpp AT delorie DOT com Subject: Re: A way to find how many files are currently 'open'? In-Reply-To: <332C8C47.59EF@osha.igs.net> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII On Sun, 16 Mar 1997, Delong wrote: > Suppose I read from this 'function', then opened a file (with 'open()'), > then read from this function again. I would expect it to return 1 more > opened file than the first time. > > Any way to do this? It would really help me find a problem I'm currently > having so let me know if you've seen one, There's no such function in the library, you will have to roll your own. One way to do that is to use the DJGPP Filesystem Extensions mechanism to install a handler for the `open' and `creat' functions and maintain a table of open files. See the library reference for more details about Filesystem Extensions (type "info libc alpha __FSEXT_add" from the DOS prompt). Another way to do that is to walk the JFT (Job File Table) which is the table of open files maintained by DOS inside the PSP of every program. The JFT is just an array of unsigned char numbers which are 255 for a file that isn't open or a number other than 255 for a file that is currently open. A real-mode-style seg:off pointer to the JFT is at offset 34h in the PSP, and the number of entries in the JFT is at offset 32h in the PSP. I recommend this method, because it is simpler in your case, and will work with all methods available to open files (the FSEXT method doesn't work if a program calls DOS directly via INT 21h or similar low-level calls). I attach below an excerpt from the DJGPP debug interface that uses both the above methods (see the comments for the reasons), written by Robert Hoehne, which is a working example of using the above techniques. If you have any further questions, please post them to the news group. --------------------------- cut here -------------------------------- /* Now the FSEXT function for watching files being opened. This is needed, because the debuggee can open files which are not closed and if you do this multiple times, the limit of max opened files is reached. The watching is done by the FSEXT function by hooking the _open(), _creat() and _close() calls from the libc functions. The only things which are added is recording files which are opened (and closed) by the debugger. When cleanup_client() is called, this list is compared with actual open files and every file, which was not seen by dbg_fsext() is closed. This technique does not work correctly when the debugger uses the lowest routines for opening/creating/closing files which are _dos_open(), _dos_creat(), _dos_creatnew() and _dos_close(). */ static unsigned char handles[256]; static int in_dbg_fsext = 0; static void close_handles(void) { __dpmi_regs r; int psp_la; int jft_ofs; int jft_count; int handle; /* Get our PSP address. */ r.x.ax = 0x6200; __dpmi_int (0x21, &r); psp_la = ( (int)r.x.bx ) << 4; /* Get the offset of the JFT table by (seg << 4) + offset */ jft_ofs = (_farpeekw(_dos_ds, psp_la + 0x36) << 4) + _farpeekw(_dos_ds, psp_la + 0x34); /* Number of used entries in the JFT table */ jft_count = _farpeekw(_dos_ds, psp_la + 0x32); /* Disable the fsext function */ in_dbg_fsext++; for (handle=0;handle %d\n",retval); #endif in_dbg_fsext--; if (retval != -1) { handles[retval] = retval; __FSEXT_set_function(retval,dbg_fsext); } break; case __FSEXT_open: filename = va_arg(_args,const char *); oflag = va_arg(_args,int); in_dbg_fsext++; retval = _open(filename,oflag); #ifdef DEBUG_DBGCOM fprintf(stderr,"_open(%s) => %d\n",filename,retval); #endif in_dbg_fsext--; if (retval != -1) { handles[retval] = retval; __FSEXT_set_function(retval,dbg_fsext); } break; case __FSEXT_close: handle = va_arg(_args,int); in_dbg_fsext++; #ifdef DEBUG_DBGCOM fprintf(stderr,"_close(%d)\n",handle); #endif retval = _close(handle); in_dbg_fsext--; if (retval == 0) { handles[handle] = 0xff; __FSEXT_set_function(handle,NULL); } break; } *_rv = retval; return 1; } /* With attribute constructor to be called automaticaly before main */ static void __attribute__((__constructor__)) _init_dbg_fsext(void) { __dpmi_regs r; int psp_la; int jft_ofs; int jft_count; /* Get our PSP address. */ r.x.ax = 0x6200; __dpmi_int (0x21, &r); psp_la = ( (int)r.x.bx ) << 4; /* Get the offset of the JFT table by (seg << 4) + offset */ jft_ofs = (_farpeekw(_dos_ds, psp_la + 0x36) << 4) + _farpeekw(_dos_ds, psp_la + 0x34); /* Number of used entries in the JFT table */ jft_count = _farpeekw(_dos_ds, psp_la + 0x32); /* Add the handler for opening/creating files */ __FSEXT_add_open_handler(dbg_fsext); /* Initialize all the handles to 0xff */ memset(handles,0xff,sizeof(handles)); /* Get a copy of all already opened handles */ movedata(_dos_ds,jft_ofs,_my_ds(),(int)handles,jft_count); /* enable the fsext function */ in_dbg_fsext = 0; }