home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 10 / 10.iso / l / l440 / 2.ddi / CHAP4 / FILES.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-14  |  9.6 KB  |  300 lines

  1. /* 
  2. FILES.C -- list all files in system file table
  3. Version No. 3 (23 March 1991)
  4. Author: Andrew Schulman (CIS 76320,302)
  5.  
  6. Microsoft C 6.0:
  7.     cl files.c
  8.     cl -DFREEUP -Fefreeup.exe files.c
  9.  
  10. Turbo C:
  11.     tcc files.c
  12.     tcc -DFREEUP -efreeup.exe files.c
  13.         
  14. This version is different from that published in BYTE, March 1991,
  15. and from code in the book UNDOCUMENTED DOS, pp. 197-201, 209-210.
  16.     -- includes DOS 3.0 file structure (USHORT dir_entry, not BYTE)
  17.     -- allows PSP +- 1 (some DOS versions store PSPowner incorrectly!)
  18.     -- fixes bug in for loops
  19.     -- points out typo printed in BYTE version (int 21h, not int 21)
  20.     -- fixes test for AUX, CON, PRN (e.g. check for "AUX " not "AUX")
  21.     -- split filename[11] into filename[8], ext[3]
  22.     -- DOS 2.x, 3.0, 3.1+ structs combined into union, with access
  23.        macros. This points up the relative inflexibility of structures:
  24.        struct->field just turns into an offset, but at compile-time,
  25.        with no control over changing field offsets at run-time.
  26.     -- points out a possible problem with the AUX-CON "sanity check."
  27.             
  28.     Future versions of FILES should also print out open/sharing modes,
  29. and drive number (inside dev_info field in DOS 3+).
  30. */
  31.  
  32. #include <stdlib.h>
  33. #include <stdio.h>
  34. #include <dos.h>
  35.  
  36. typedef unsigned char BYTE;
  37. typedef unsigned USHORT;
  38. typedef unsigned long ULONG;
  39. typedef BYTE far *FP;
  40.  
  41. #pragma pack(1)
  42.  
  43. typedef struct file2 {   
  44.     BYTE num_handles, open_mode;
  45.     BYTE fattr;     // might not be accurate??
  46.     BYTE drive;
  47.     BYTE filename[8], ext[3];
  48.     USHORT unknown1, unknown2;
  49.     ULONG fsize;
  50.     // ...
  51.     // NOTE! no owner_psp!
  52.     } file2; // for DOS 2.x, see UNDOCUMENTED DOS, p. 526
  53.     
  54. typedef struct file30 {   
  55.     USHORT num_handles, open_mode;
  56.     BYTE fattr;
  57.     USHORT dev_info;    // includes drive number
  58.     FP ptr;
  59.     USHORT start_cluster, time, date;
  60.     ULONG fsize, offset;
  61.     USHORT rel_cluster, abs_cluster, dir_sector;
  62.     USHORT dir_entry;    // only difference from file31: USHORT, not BYTE
  63.     BYTE filename[8], ext[3];
  64.     ULONG share_prev_sft;
  65.     USHORT share_net_machine;
  66.     USHORT owner_psp;
  67.     // ...
  68.     } file30; // for DOS 3.0 only
  69.     
  70. typedef struct file31 {   
  71.     USHORT num_handles, open_mode;
  72.     BYTE fattr;
  73.     USHORT dev_info;    // includes drive number
  74.     FP ptr;
  75.     USHORT start_cluster, time, date;
  76.     ULONG fsize, offset;
  77.     USHORT rel_cluster, abs_cluster, dir_sector;
  78.     BYTE dir_entry;
  79.     BYTE filename[8], ext[3];
  80.     ULONG share_prev_sft;
  81.     USHORT share_net_machine;
  82.     USHORT owner_psp;
  83.     // ...
  84.     } file31; // for DOS 3.1+, 4.x, see UNDOCUMENTED DOS, pp. 527-528
  85.         
  86. typedef union file {
  87.     file2 f2;
  88.     file30 f30;
  89.     file31 f31;
  90.     } file;
  91.     
  92. #define DOSVER_FIELD(pf,x) \
  93.     (_osmajor == 2) ?                   pf->f2.x : \
  94.     (_osmajor == 3 && _osminor == 0) ?  pf->f30.x : \
  95.     /* DOS 3.1+ */                      pf->f31.x
  96.  
  97. // access macros
  98. #define FILENAME(pf)    DOSVER_FIELD(pf,filename)
  99. #define EXT(pf)         DOSVER_FIELD(pf,ext)
  100. #define FSIZE(pf)       DOSVER_FIELD(pf,fsize)
  101. #define FATTR(pf)       DOSVER_FIELD(pf,fattr)
  102. #define NUM_HANDLES(pf) DOSVER_FIELD(pf,num_handles)
  103.  
  104. #define NUM_HANDLES_LVALUE(pf)  *((USHORT far *) pf)
  105.  
  106. // treat OWNER_PSP separately in DOS2, because no owner_psp field
  107. #define OWNER_PSP(pf)   \
  108.     (_osmajor == 2) ?                   -1 : \
  109.     (_osmajor == 3 && _osminor == 0) ?  pf->f30.owner_psp : \
  110.     /* DOS 3.1+ */                      pf->f31.owner_psp
  111.         
  112. typedef struct sysftab {
  113.     struct sysftab far *next;
  114.     USHORT num_files;
  115.     file f[1];
  116.     } SYS_FTAB;     // see UNDOCUMENTED DOS, pp. 526-527
  117.     
  118. typedef struct {
  119.     BYTE type;      
  120.     USHORT owner;    /* PSP of the owner */
  121.     USHORT size;
  122.     BYTE unused[3];
  123.     BYTE dos4[8];
  124.     } MCB;      // see UNDOCUMENTED DOS, p. 520
  125.  
  126. void fail(char *s) { puts(s); exit(1); }    
  127.  
  128. #ifdef __TURBOC__
  129. #define GETVECT(intno)  getvect(intno)
  130. #define ASM             asm
  131. #else
  132. #define GETVECT(intno)  _dos_getvect(intno)
  133. #define ASM             _asm
  134. #endif
  135.  
  136. #ifndef MK_FP
  137. #define MK_FP(seg,ofs)  ((FP)(((ULONG)(seg) << 16) | (ofs)))
  138. #endif
  139.  
  140. #define NEXT(mcb)       (MK_FP(FP_SEG(mcb) + (mcb)->size + 1, 0))
  141.  
  142. int belongs(FP vec, USHORT start, USHORT size)
  143. {
  144.     USHORT seg = FP_SEG(vec) + (FP_OFF(vec) >> 4);
  145.     return (seg >= start) && (seg <= (start + size));
  146. }
  147.  
  148. int is_psp(USHORT seg)
  149. {
  150.     return ((((MCB far *) MK_FP(seg-1,0))->owner == seg) &&
  151.             (*((USHORT far *) MK_FP(seg,0)) == 0x20CD));
  152. }
  153.                 
  154. /*
  155.     Look for "orphaned" file handles: e.g., TSR>FOO.BAR or TSR>NUL
  156.     will leave FOO.BAR or NUL entry in SFT, consuming file handle. If
  157.     the PSP of the file's owner is COMMAND.COM, and if there's only
  158.     one owner, then we decide it's an orphaned handle.
  159. */
  160. int orphan(file far *ff)
  161. {
  162.     static command_com_psp = 0;
  163.     if (! NUM_HANDLES(ff))
  164.         return 0;
  165.     if (! command_com_psp)  /* do just one time */
  166.     {
  167.         FP int2e = (FP) GETVECT(0x2E); // won't work under MKS Toolkit SH.EXE!
  168.         MCB far *mcb;
  169.         ASM mov ah, 52h
  170.         ASM int 21h         // the 'h' was left out in BYTE!
  171.         ASM mov ax, es:[bx-2]
  172.         ASM mov word ptr mcb+2, ax
  173.         ASM mov word ptr mcb, 0
  174.         while (mcb->type != 'Z')
  175.             if (belongs(int2e, FP_SEG(mcb), mcb->size))
  176.             {
  177.                 command_com_psp = mcb->owner;
  178.                 break;
  179.             }
  180.             else
  181.                 mcb = (MCB far *) NEXT(mcb);
  182.     }
  183.     return ((OWNER_PSP(ff) == command_com_psp) &&
  184.             (NUM_HANDLES(ff) == 1));
  185. }
  186.  
  187. /* changed from the March 1991 BYTE article and from UNDOCUMENTED 
  188. DOS, p. 199 */
  189. #define IS_AUX(s) (s[0]=='A' && s[1]=='U' && s[2]=='X' && s[3] == ' ')
  190. #define IS_CON(s) (s[0]=='C' && s[1]=='O' && s[2]=='N' && s[3] == ' ')
  191. #define IS_PRN(s) (s[0]=='P' && s[1]=='R' && s[2]=='N' && s[3] == ' ')
  192.  
  193. main(void)
  194. {
  195.     SYS_FTAB far *sys_filetab;
  196.     file far *ff;
  197.     int size;
  198.     int i;
  199.  
  200.     ASM mov ah, 52h
  201.     ASM int 21h         // the 'h' was left out in BYTE!
  202.     ASM les bx, dword ptr es:[bx+4] /* ptr to list of DOS file tables */
  203.     ASM mov word ptr sys_filetab, bx
  204.     ASM mov word ptr sys_filetab+2, es
  205.  
  206.     /* DOS box of OS/2 1.x doesn't provide system file tbl */
  207.     if (sys_filetab == (SYS_FTAB far *) -1L)
  208.         fail("system file table not supported");
  209.  
  210.     switch (_osmajor)
  211.     {
  212.         case 2:             size = 0x28; break;
  213.         case 3:             size = 0x35; break;
  214.         default:            size = 0x3b; break;
  215.     }
  216.  
  217.     /* Perform sanity check: determine size of file structure
  218.        empirically from difference between strings "CON" and
  219.        "AUX." If this equals size computed via _osmajor, everything
  220.        is fine. Otherwise, we reset size. */
  221.     /* NOTE: But maybe this "sanity check" ain't so sane, since
  222.        it depends on the placement of AUX before CON in the SFTs,
  223.        which is by no means a requirement of the undocumented DOS
  224.        "spec." */
  225.     {
  226.         FP p, q;
  227.         int i;
  228.         /* i=1000: set upper limit on string search in memory */
  229.         for (p=(FP)sys_filetab->f, i=1000; p++, i--; )
  230.             if (IS_AUX(p))
  231.                 break;
  232.         if (! i) 
  233.             return 1;
  234.         for (q=p, i=1000; q++, i--; )
  235.             if (IS_CON(q))
  236.                 break;
  237.         if (! i) 
  238.             return 1;
  239.         /* size of file structure must equal span from AUX to CON */
  240.         if (size != (q - p))
  241.         {
  242.             puts("warning: size based on _osmajor looks wrong");
  243.             size = q - p;
  244.         }
  245.     }
  246.  
  247.     printf("Filename              Size      Attr Handles    Owner\n");
  248.     printf("--------              ----      ---- -------    -----\n");
  249.  
  250.     do { /* FOR EACH SFT */
  251.         
  252.         /* FOR EACH ENTRY IN THIS SFT */
  253.         for (i=sys_filetab->num_files, ff=sys_filetab->f; 
  254.              i--; 
  255.              ((FP) ff) += size)
  256.         if (NUM_HANDLES(ff))
  257.         {
  258.             printf("%.8Fs.",   FILENAME(ff));
  259.             printf("%.3Fs\t",  EXT(ff));
  260.             printf("%10lu\t",  FSIZE(ff));
  261.             printf("%04X\t",   FATTR(ff));
  262.             printf("%d\t",     NUM_HANDLES(ff));
  263.             if (_osmajor > 2)
  264.             {
  265.                 USHORT owner = OWNER_PSP(ff);   // not in DOS2
  266.                 char far *name;
  267.                 printf("%04X\t", owner);
  268.                 if ((! is_psp(owner)) &&    // allow off-by-one
  269.                     (! is_psp(owner - 1)) &&
  270.                     (! is_psp(owner + 1)))
  271.                         printf("[NOT PSP]");
  272.                 if (orphan(ff))
  273.                     printf("[ORPHAN]");
  274. #ifdef FREEUP
  275.                 // only DOS 3+
  276.                 name = FILENAME(ff);
  277.                 if (! IS_AUX(name)) 
  278.                 if (! IS_CON(name))
  279.                 if (! IS_PRN(name))
  280.                 if (orphan(ff) || 
  281.                    ((! is_psp(owner)) &&        // allow off-by-one
  282.                     (! is_psp(owner - 1)) &&
  283.                     (! is_psp(owner + 1))))
  284.                 {
  285.                     if (! (-- NUM_HANDLES_LVALUE(ff))) // decrement owners
  286.                         printf(" [FREED]");
  287.                     else
  288.                         printf(" [NOW %d]", NUM_HANDLES(ff));
  289.                 }
  290. #endif
  291.             }
  292.             printf("\n");
  293.         }
  294.         sys_filetab = sys_filetab->next; /* FOLLOWED LINKED LIST... */
  295.     } while (FP_SEG(sys_filetab) && 
  296.              FP_OFF(sys_filetab) != (unsigned) -1); /* ...UNTIL END */
  297.     return 0;
  298. }
  299.  
  300.