home *** CD-ROM | disk | FTP | other *** search
- /*
- FILES.C -- list all files in system file table
- Version No. 3 (23 March 1991)
- Author: Andrew Schulman (CIS 76320,302)
-
- Microsoft C 6.0:
- cl files.c
- cl -DFREEUP -Fefreeup.exe files.c
-
- Turbo C:
- tcc files.c
- tcc -DFREEUP -efreeup.exe files.c
-
- This version is different from that published in BYTE, March 1991,
- and from code in the book UNDOCUMENTED DOS, pp. 197-201, 209-210.
- -- includes DOS 3.0 file structure (USHORT dir_entry, not BYTE)
- -- allows PSP +- 1 (some DOS versions store PSPowner incorrectly!)
- -- fixes bug in for loops
- -- points out typo printed in BYTE version (int 21h, not int 21)
- -- fixes test for AUX, CON, PRN (e.g. check for "AUX " not "AUX")
- -- split filename[11] into filename[8], ext[3]
- -- DOS 2.x, 3.0, 3.1+ structs combined into union, with access
- macros. This points up the relative inflexibility of structures:
- struct->field just turns into an offset, but at compile-time,
- with no control over changing field offsets at run-time.
- -- points out a possible problem with the AUX-CON "sanity check."
-
- Future versions of FILES should also print out open/sharing modes,
- and drive number (inside dev_info field in DOS 3+).
- */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <dos.h>
-
- typedef unsigned char BYTE;
- typedef unsigned USHORT;
- typedef unsigned long ULONG;
- typedef BYTE far *FP;
-
- #pragma pack(1)
-
- typedef struct file2 {
- BYTE num_handles, open_mode;
- BYTE fattr; // might not be accurate??
- BYTE drive;
- BYTE filename[8], ext[3];
- USHORT unknown1, unknown2;
- ULONG fsize;
- // ...
- // NOTE! no owner_psp!
- } file2; // for DOS 2.x, see UNDOCUMENTED DOS, p. 526
-
- typedef struct file30 {
- USHORT num_handles, open_mode;
- BYTE fattr;
- USHORT dev_info; // includes drive number
- FP ptr;
- USHORT start_cluster, time, date;
- ULONG fsize, offset;
- USHORT rel_cluster, abs_cluster, dir_sector;
- USHORT dir_entry; // only difference from file31: USHORT, not BYTE
- BYTE filename[8], ext[3];
- ULONG share_prev_sft;
- USHORT share_net_machine;
- USHORT owner_psp;
- // ...
- } file30; // for DOS 3.0 only
-
- typedef struct file31 {
- USHORT num_handles, open_mode;
- BYTE fattr;
- USHORT dev_info; // includes drive number
- FP ptr;
- USHORT start_cluster, time, date;
- ULONG fsize, offset;
- USHORT rel_cluster, abs_cluster, dir_sector;
- BYTE dir_entry;
- BYTE filename[8], ext[3];
- ULONG share_prev_sft;
- USHORT share_net_machine;
- USHORT owner_psp;
- // ...
- } file31; // for DOS 3.1+, 4.x, see UNDOCUMENTED DOS, pp. 527-528
-
- typedef union file {
- file2 f2;
- file30 f30;
- file31 f31;
- } file;
-
- #define DOSVER_FIELD(pf,x) \
- (_osmajor == 2) ? pf->f2.x : \
- (_osmajor == 3 && _osminor == 0) ? pf->f30.x : \
- /* DOS 3.1+ */ pf->f31.x
-
- // access macros
- #define FILENAME(pf) DOSVER_FIELD(pf,filename)
- #define EXT(pf) DOSVER_FIELD(pf,ext)
- #define FSIZE(pf) DOSVER_FIELD(pf,fsize)
- #define FATTR(pf) DOSVER_FIELD(pf,fattr)
- #define NUM_HANDLES(pf) DOSVER_FIELD(pf,num_handles)
-
- #define NUM_HANDLES_LVALUE(pf) *((USHORT far *) pf)
-
- // treat OWNER_PSP separately in DOS2, because no owner_psp field
- #define OWNER_PSP(pf) \
- (_osmajor == 2) ? -1 : \
- (_osmajor == 3 && _osminor == 0) ? pf->f30.owner_psp : \
- /* DOS 3.1+ */ pf->f31.owner_psp
-
- typedef struct sysftab {
- struct sysftab far *next;
- USHORT num_files;
- file f[1];
- } SYS_FTAB; // see UNDOCUMENTED DOS, pp. 526-527
-
- typedef struct {
- BYTE type;
- USHORT owner; /* PSP of the owner */
- USHORT size;
- BYTE unused[3];
- BYTE dos4[8];
- } MCB; // see UNDOCUMENTED DOS, p. 520
-
- void fail(char *s) { puts(s); exit(1); }
-
- #ifdef __TURBOC__
- #define GETVECT(intno) getvect(intno)
- #define ASM asm
- #else
- #define GETVECT(intno) _dos_getvect(intno)
- #define ASM _asm
- #endif
-
- #ifndef MK_FP
- #define MK_FP(seg,ofs) ((FP)(((ULONG)(seg) << 16) | (ofs)))
- #endif
-
- #define NEXT(mcb) (MK_FP(FP_SEG(mcb) + (mcb)->size + 1, 0))
-
- int belongs(FP vec, USHORT start, USHORT size)
- {
- USHORT seg = FP_SEG(vec) + (FP_OFF(vec) >> 4);
- return (seg >= start) && (seg <= (start + size));
- }
-
- int is_psp(USHORT seg)
- {
- return ((((MCB far *) MK_FP(seg-1,0))->owner == seg) &&
- (*((USHORT far *) MK_FP(seg,0)) == 0x20CD));
- }
-
- /*
- Look for "orphaned" file handles: e.g., TSR>FOO.BAR or TSR>NUL
- will leave FOO.BAR or NUL entry in SFT, consuming file handle. If
- the PSP of the file's owner is COMMAND.COM, and if there's only
- one owner, then we decide it's an orphaned handle.
- */
- int orphan(file far *ff)
- {
- static command_com_psp = 0;
- if (! NUM_HANDLES(ff))
- return 0;
- if (! command_com_psp) /* do just one time */
- {
- FP int2e = (FP) GETVECT(0x2E); // won't work under MKS Toolkit SH.EXE!
- MCB far *mcb;
- ASM mov ah, 52h
- ASM int 21h // the 'h' was left out in BYTE!
- ASM mov ax, es:[bx-2]
- ASM mov word ptr mcb+2, ax
- ASM mov word ptr mcb, 0
- while (mcb->type != 'Z')
- if (belongs(int2e, FP_SEG(mcb), mcb->size))
- {
- command_com_psp = mcb->owner;
- break;
- }
- else
- mcb = (MCB far *) NEXT(mcb);
- }
- return ((OWNER_PSP(ff) == command_com_psp) &&
- (NUM_HANDLES(ff) == 1));
- }
-
- /* changed from the March 1991 BYTE article and from UNDOCUMENTED
- DOS, p. 199 */
- #define IS_AUX(s) (s[0]=='A' && s[1]=='U' && s[2]=='X' && s[3] == ' ')
- #define IS_CON(s) (s[0]=='C' && s[1]=='O' && s[2]=='N' && s[3] == ' ')
- #define IS_PRN(s) (s[0]=='P' && s[1]=='R' && s[2]=='N' && s[3] == ' ')
-
- main(void)
- {
- SYS_FTAB far *sys_filetab;
- file far *ff;
- int size;
- int i;
-
- ASM mov ah, 52h
- ASM int 21h // the 'h' was left out in BYTE!
- ASM les bx, dword ptr es:[bx+4] /* ptr to list of DOS file tables */
- ASM mov word ptr sys_filetab, bx
- ASM mov word ptr sys_filetab+2, es
-
- /* DOS box of OS/2 1.x doesn't provide system file tbl */
- if (sys_filetab == (SYS_FTAB far *) -1L)
- fail("system file table not supported");
-
- switch (_osmajor)
- {
- case 2: size = 0x28; break;
- case 3: size = 0x35; break;
- default: size = 0x3b; break;
- }
-
- /* Perform sanity check: determine size of file structure
- empirically from difference between strings "CON" and
- "AUX." If this equals size computed via _osmajor, everything
- is fine. Otherwise, we reset size. */
- /* NOTE: But maybe this "sanity check" ain't so sane, since
- it depends on the placement of AUX before CON in the SFTs,
- which is by no means a requirement of the undocumented DOS
- "spec." */
- {
- FP p, q;
- int i;
- /* i=1000: set upper limit on string search in memory */
- for (p=(FP)sys_filetab->f, i=1000; p++, i--; )
- if (IS_AUX(p))
- break;
- if (! i)
- return 1;
- for (q=p, i=1000; q++, i--; )
- if (IS_CON(q))
- break;
- if (! i)
- return 1;
- /* size of file structure must equal span from AUX to CON */
- if (size != (q - p))
- {
- puts("warning: size based on _osmajor looks wrong");
- size = q - p;
- }
- }
-
- printf("Filename Size Attr Handles Owner\n");
- printf("-------- ---- ---- ------- -----\n");
-
- do { /* FOR EACH SFT */
-
- /* FOR EACH ENTRY IN THIS SFT */
- for (i=sys_filetab->num_files, ff=sys_filetab->f;
- i--;
- ((FP) ff) += size)
- if (NUM_HANDLES(ff))
- {
- printf("%.8Fs.", FILENAME(ff));
- printf("%.3Fs\t", EXT(ff));
- printf("%10lu\t", FSIZE(ff));
- printf("%04X\t", FATTR(ff));
- printf("%d\t", NUM_HANDLES(ff));
- if (_osmajor > 2)
- {
- USHORT owner = OWNER_PSP(ff); // not in DOS2
- char far *name;
- printf("%04X\t", owner);
- if ((! is_psp(owner)) && // allow off-by-one
- (! is_psp(owner - 1)) &&
- (! is_psp(owner + 1)))
- printf("[NOT PSP]");
- if (orphan(ff))
- printf("[ORPHAN]");
- #ifdef FREEUP
- // only DOS 3+
- name = FILENAME(ff);
- if (! IS_AUX(name))
- if (! IS_CON(name))
- if (! IS_PRN(name))
- if (orphan(ff) ||
- ((! is_psp(owner)) && // allow off-by-one
- (! is_psp(owner - 1)) &&
- (! is_psp(owner + 1))))
- {
- if (! (-- NUM_HANDLES_LVALUE(ff))) // decrement owners
- printf(" [FREED]");
- else
- printf(" [NOW %d]", NUM_HANDLES(ff));
- }
- #endif
- }
- printf("\n");
- }
- sys_filetab = sys_filetab->next; /* FOLLOWED LINKED LIST... */
- } while (FP_SEG(sys_filetab) &&
- FP_OFF(sys_filetab) != (unsigned) -1); /* ...UNTIL END */
- return 0;
- }
-
-