Finding Handles From File Names

File system names are recorded in the MFT control block. Each MFT has a handle, which is its linear address and a key which is the concatenation of the hVPB with the file name considered as a string of bytes. The MFT keys are managed in a Patricia Tree structure similar to that described by Knuth in The Art of computer Programming, Volume 3, Sorting and Searching Algorithms However, note that the implementation of the PTree in OS/2 is slightly modified from the Knuth treatment.

The SAS gives us the address of the header node for the MFT PTree. The header node points to the first PTree entry. Each entry comprises a bit index, a key length, a left pointer, a right pointer and an MFT handle. The bit-index is used to specify the bit in the key to be tested. If the bit 0 then the left pointer is taken, otherwise the right pointer is taken. When the selected pointer points back to the same PTree entry then the search stops and the required MFT is found from the MFT handle. The bit index count the bits of each byte of the key from left to right.

This technique is now illustrated in the following example:

>>> Who's got C:\OS2\HELP\HMHELP.HLP open?

>>> First look through VPBs to find hVPB for C:
>>> Find the VPB segment and chain through them starting with the
>>> first at offset 0x12.

# ln gdt_vpb
0138:00000098 OS2KRNL GDT_VPB
# .d vpb 98:12
        vpb_flink: 0000                  vpdFAT_cluster_mask: 02
        vpb_blink: 008d                 vpdFAT_cluster_shift: 00
    vpb_ref_count: 0057                     vpdFAT_first_FAT: 0000
 vpb_search_count: 0004                     vpdFAT_FAT_count: 00
 vpb_first_access: 00                    vpdFAT_root_entries: 0030
    vpb_signature: 444a                  vpdFAT_first_sector: 06001100
     vpb_flags(2): 02:00                  vpdFAT_max_cluster: 7d5c
          vpb_FSC: #00c8:0008                vpdFAT_FAT_size: b213
           vpi_ID: 25be2014                vpdFAT_dir_sector: fc04b800
         vpi_pDPB: #04c8:0038                   vpdFAT_media: 0a
     vpi_cbSector: 0200                     vpdFAT_next_free: 00b2
       vpi_totsec: 00049020                  vpdFAT_free_cnt: 04b8
       vpi_trksec: 0023                  vpdFAT_FATentrysize: b2
        vpi_nhead: 000c                      vpdFAT_IDsector: 00000000
         vpi_pDCS: #0000:0000                  vpdFAT_access: 0000
         vpi_pVCS: #0000:0000                 vpdFAT_accwait: 0000
        vpi_drive: 02                          vpdFAT_pEASFT: #0000:0000
         vpi_unit: 02
         vpi_text: UNLABELED
         vpi_flags: 0003

>>> We get lucky the first time. This VPD is for drive 2, that is C:
>>> So the hVPB=0012 (i.e the offset into the VPD segment).

>>> We now need to form the MFT key for the file name we wish to
>>> look up. So convert the file name to ASCII and concatenate to the
>>> hVPB (as a byte pair, that is, reversed)
>>>       C  :  \  O  S  2  \  H  E  L  P  \  H  M  H  E  L  P  .  H  L  P
>>> 12 00 43 3a 5c 4f 53 32 5c 48 45 4c 50 5c 48 4d 48 45 4c 50 2e 48-4c 50

>>> Locate the MFT PTree head from the SAS - in a dump use .A
>>> otherwise unravel the SAS from selector 70

# .a
--- SAS Base Section ---
                      SAS signature: SAS
           offset to tables section: 0016
      FLAT selector for kernel data: 0168
    offset to configuration section: 001E
    offset to device driver section: 0020
   offset to Virtual Memory section: 002C
          offset to Tasking section: 005C
              offset to RAS section: 006E
      offset to File System section: 0074
          offset to infoseg section: 0080
--- SAS Protected Modes Tables Section ---
                   selector for GDT: 0008
                   selector for LDT: 0000
                   selector for IDT: 0018
               selector for GDTPOOL: 0100
--- SAS Device Driver Section ---
    offset for the first bimodal dd: 0CB9
  offset for the first real mode dd: 0000
      sel for Drive Parameter Block: 04C8
       sel for ABIOS prot. mode CDA: 0000
        seg for ABIOS real mode CDA: 0000
                   selector for FSC: 00C8
--- SAS Task Section ---
          selector for current PTDA: 0030
  FLAT offset for process tree head: FFF10910
 FLAT address for TCB address array: FFF06BB6
      offset for current TCB number: FFDFFB5E
             offset for ThreadCount: FFDFFB62
--- SAS File System Section ---
                handle to MFT PTree: FE72CFBC
     selector for System File Table: 00C0
     sel. for Volume Parameter Bloc: 0788
   sel. for Current Directory Struc: 07B8
        selector for buffer segment: 00A8
--- SAS Information Segment Section ---
       selector for global info seg: 0428
   address of curtask local infoseg: 03C80000
      address of DOS task's infoseg: FFFFFFFF
         selector for Codepage Data: 07CB
--- SAS RAS Section ---
selector for System Trace Data Area: 04B0
 segment for System Trace Data Area: 04B0
        offset for trace event mask: 0B28
--- SAS Configuration Section ---
    offset for Device Config. Table: 0D50
--- SAS Virtual Memory Mgt. Section ---
       Flat offset of arena records: FFF13304
      Flat offset of object records: FFF1331C
     Flat offset of context records: FFF1330C
  Flat offset of kernel mte records: FFF0A891
     Flat offset of linked mte list: FFF07934
    Flat offset of page frame table: FFF11A70
    Flat offset of page range table: FFF111EC
    Flat offset of swap frame array: FFF03BAC
           Flat offset of Idle Head: FFF10090
           Flat offset of Free Head: FFF10080
          Flat offset of Heap Array: FFF11B78
     Flat offset of all mte records: FFF12E04

>>> MFT Ptree is at %fe72cfbc
>>> each entry including the header has the following format:
>>> +0 W Bit index
>>> +2 W key length
>>> +4 D left link
>>> +8 D right link
>>> +c D MFT handle (MFT pointer)

>>> dump the header and the first entry pointed to by the left link
# dd %FE72CFBC l4
%fe72cfbc  ffffffff fe867f10 fe72cfbc 00000000
# dd %FE867f10 l4
%fe867f10  00100000 fe861454 fe861470 fe721a04
>>>        ----.... -------- -------- --------
>>>         Kl  BI    left     right    MFT
>>>
>>> Note the word reversal of the Bit index and the Key length because
>>> we dumped double-words.
>>> BI tells us to test bit 0 of the key (numbering from the left
>>> starting with 0). 12 00 .. .. .. = 0001 0010 0000 0000 .... ....
>>> Bit zero is 0 so take the left link.

# dd %FE861454 l4
%fe861454  00100001 fe73d194 fe845370 fe72196c

>>> Now test bit 1. This is still zero. Again take the left link.

# dd %FE73d194 l4
%fe73d194  00190003 fe72cf3c fe87ec34 fe72dea4

>>> Now test bit 3. This is 1 so take the right link.

# dd %FE87ec34 l4
%fe87ec34  000b0029 fe87ebdc fe834308 fe87ebf0

>>> Now test bit 29.  ..... 4f .... = 0100 1111
>>> This is 1 so take the right link.

# dd %FE834308 l4
%fe834308  0019002b fe869f30 fe834254 fe834274

>>> Test bit 2b. This is 0. Turn left.

# dd %FE869f30 l4
%fe869f30  0017002c fe885ac4 fe87ec90 fe869ee0

>>> Test bit 2c. This is 1. Turn right.

# dd %FE87ec90 l4
%fe87ec90  000f002d fe87ec90 fe834ac8 fe87ec48

>>> Test bit 2d. This is 1. Turn right.

# dd %FE834ac8 l4
%fe834ac8  001a0044 fe845ef8 fe724fe4 fe845c0c

>>> Test bit 44. .....5c.... = 0101 1100.
>>> This is 1. Turn right.

# dd %FE724fe4 l4
%fe724fe4  001b004b fe801414 fe862de8 fe722fac

>>> Test bit 4b. .....48..... = 0100 1000
>>> This is 0. Turn left.

# dd %FE801414 l4
%fe801414  0017004c fe801d90 fe7cef84 fe7dffb0

>>> Test bit 4c. This is 1. Turn right.

# dd %FE7cef84 l4
%fe7cef84  00180073 fe7cef84 fe801414 fe7cef30

>>> Test bit 73. .....48.... = 0100 1000
>>> This is zero and the left link points to the same node.
>>> Therefore the search ends and we should have found the MFT
>>> for our file name. Dump the MFT to check .....


# db %FE7cef30 l50
%fe7cef30 4b 53 45 4d 01 02 00 00-00 00 00 00 00 00 00 00 KSEM............
%fe7cef40 00 00 28 31 38 04 00 00-00 00 4b 53 45 4d 01 02 ..(18.....KSEM..
%fe7cef50 00 00 00 00 00 00 00 00-00 00 00 00 69 03 00 00 ............i...
%fe7cef60 6d 46 12 00 43 3a 5c 4f-53 32 5c 48 45 4c 50 5c mF..C:\OS2\HELP\
%fe7cef70 48 4d 48 45 4c 50 2e 48-4c 50 00 00 16 e6 7c fe HMHELP.HLP...f|~

>>> The MFT + 0x22 points is the SFT segment's offset. So dump the
>>> SFT ....

# ln gdt_sft
0138:000000c0 OS2KRNL GDT_SFT
dw c0:0l1
#00c0:00000000 0438

# .d sft 438:3128
      sf_ref_count: 0001                        sfi_mode: 00a0
        sf_usercnt: 0000                        sfi_hVPB: 0012
          reserved: 00                         sfi_ctime: 0000
       sf_flags(2): 0000:0000                  sfi_cdate: 0000
         sf_devptr: #0000:0000                 sfi_atime: 0000
            sf_FSC: #00c8:0008                 sfi_adate: 0000
          sf_chain: #0438:33b7                 sfi_mtime: 0000
            sf_MFT: fe7cef30                   sfi_mdate: 0000
sfdFAT_firFILEclus: 3344                        sfi_size: 00007058
    sfdFAT_cluspos: 0f10                    sfi_position: 00000a90
    sfdFAT_lstclus: 0000                         sfi_UID: 0000
     sfdFAT_dirsec: 00000000                     sfi_PID: 0012
     sfdFAT_dirpos: 00                           sfi_PDB: 0000
       sfdFAT_name:                       sfi_selfsfn: 0060
   sfdFAT_EAHandle: 0000                      sfi_tstamp: 00
          sf_plock: 0000                     sfi_DOSattr: 00
      sf_NmPipeSfn: 0000
       sf_codepage: 0000

>>> sfi_PID tells us PID 12 has opened this file. But the
>>> sf_chain is not zero, so other processes have also opened
>>> this file. Follow the sf_chain .....

# .d sft 438:33b7
      sf_ref_count: 0001                        sfi_mode: 00a0
        sf_usercnt: 0000                        sfi_hVPB: 0012
          reserved: 00                         sfi_ctime: 0000
       sf_flags(2): 0000:0000                  sfi_cdate: 0000
         sf_devptr: #0000:0000                 sfi_atime: 0000
            sf_FSC: #00c8:0008                 sfi_adate: 0000
          sf_chain: #0438:2d10                 sfi_mtime: 0000
            sf_MFT: fe7cef30                   sfi_mdate: 0000
sfdFAT_firFILEclus: 284a                        sfi_size: 00007058
    sfdFAT_cluspos: 0f10                    sfi_position: 00000a90
    sfdFAT_lstclus: 0000                         sfi_UID: 0000
     sfdFAT_dirsec: 00000000                     sfi_PID: 000c
     sfdFAT_dirpos: 00                           sfi_PDB: 0000
       sfdFAT_name:                       sfi_selfsfn: 0065
   sfdFAT_EAHandle: 0000                      sfi_tstamp: 00
          sf_plock: 0000                     sfi_DOSattr: 00
      sf_NmPipeSfn: 0000
       sf_codepage: 0000


# .d sft 438:2d10
      sf_ref_count: 0001                        sfi_mode: 00a0
        sf_usercnt: 0000                        sfi_hVPB: 0012
          reserved: 00                         sfi_ctime: 0000
       sf_flags(2): 0000:0000                  sfi_cdate: 0000
         sf_devptr: #0000:0000                 sfi_atime: 0000
            sf_FSC: #00c8:0008                 sfi_adate: 0000
          sf_chain: #0438:2e16                 sfi_mtime: 0000
            sf_MFT: fe7cef30                   sfi_mdate: 0000
sfdFAT_firFILEclus: 1986                        sfi_size: 00007058
    sfdFAT_cluspos: 0f10                    sfi_position: 00000a90
    sfdFAT_lstclus: 0000                         sfi_UID: 0000
     sfdFAT_dirsec: 00000000                     sfi_PID: 000b
     sfdFAT_dirpos: 00                           sfi_PDB: 0000
       sfdFAT_name:                       sfi_selfsfn: 0058
   sfdFAT_EAHandle: 0000                      sfi_tstamp: 00
          sf_plock: 0000                     sfi_DOSattr: 00
      sf_NmPipeSfn: 0000
       sf_codepage: 0000


# .d sft 438:2e16
      sf_ref_count: 0001                        sfi_mode: 00a0
        sf_usercnt: 0000                        sfi_hVPB: 0012
          reserved: 00                         sfi_ctime: 0000
       sf_flags(2): 0000:0000                  sfi_cdate: 0000
         sf_devptr: #0000:0000                 sfi_atime: 0000
            sf_FSC: #00c8:0008                 sfi_adate: 0000
          sf_chain: #0000:0000                 sfi_mtime: 3ca2
            sf_MFT: fe7cef30                   sfi_mdate: 1d62
sfdFAT_firFILEclus: 050c                        sfi_size: 00007058
    sfdFAT_cluspos: 0f10                    sfi_position: 00000a90
    sfdFAT_lstclus: 0000                         sfi_UID: 0000
     sfdFAT_dirsec: 00000000                     sfi_PID: 000d
     sfdFAT_dirpos: 00                           sfi_PDB: 0000
       sfdFAT_name: SINGLEQ$                      sfi_selfsfn: 005a
   sfdFAT_EAHandle: 0000                      sfi_tstamp: 00
          sf_plock: 0000                     sfi_DOSattr: 00
      sf_NmPipeSfn: 0000
       sf_codepage: 0000

>>> In all, PIDs 0012, 000c, 000b and 000d have opened
>>> C:\OS2\HELP\HMHELP.HLP


[Back: Finding Files From Handles in a VDM]
[Next: The Record Lock Record]