MIAMEX 178: Establish File Hooks

Updated September 2017

xcall MIAMEX, MX_FILEHOOK, opcode, status, file {,fid, handler, events, flags, enabled}

The file hook mechanism allows you to establish file "hooks" on specific files and file events. The "hook" is a means by which you can insert a call to a "handler" (sometimes referred to as a "plug-in") into the midst of what would otherwise be an entirely internal operation, allowing you to monitor, filter, or otherwise customize the operation. Typical uses for file hooks are:  

•   audit trails

•   event logs

•   exporting changes

•   enforcing access security rules

Parameters

opcode  (Num)  [in]

may be one of the following (defined in ashinc:hook.def):

Symbol

Value

Meaning

HOOKOP_DISABLE

0

disable one (or all) hooks

HOOKOP_ENABLE

1

re-enable one (or all) hooks

HOOKOP_ADD

2

add a new hook

HOOKOP_DEL

3

delete a hook

HOOKOP_APPEVENT

6

call the hook to process an app-defined event

HOOKOP_QRY

7

query a file hook by its fileid or filespec. If found, the status will be >= 0 and all of the remaining fields will be returned. See the sample/utility program QRYHOOKS in EXLIB:[908,50] for examples of querying the file hook table.

Definition File: ashinc:hook.def

 

status  (Signed Num)  [out]

returns status code:

Value

Meaning

>=0

success

-1

unable to allocate memory for hook table

-2

illegal fspec (must be AMOS-style)

-3

invalid handler syntax

-4

fspec not found (opcode 0,1,2,6)

-5

fid not found (opcode 0,1,2,6)

-6

opcode not yet implemented

-7

illegal opcode

 

file  (String)  [in]

is the specification of the file whose operations are to be hooked. Only AMOS-compatible filespecs are supported. Note that with opcode 0, 1 and 3, file may be "*" to perform the operation on all the hooks in the hook table. Note that in the case of ISAM and ISAM-A files, you must specify the extension, typically IDA or DAT.

fid  (Num)  [in]

a unique integer identifier for the file, which will be used in any output files to reference the file (more compact than outputting the file spec each time.)

handler  (String)  [in]

depends on opcode. For opcode 2 (HOOKOP_ADD), it must specify the handler for the hook, using one of the following syntax variations:

SBX:sbxnam

LOGFIL:fspec

 

In the case of the SBX:sbxnam handler, A-Shell will XCALL the specified SBX subroutine (sbxnam) to process the hook, allowing you to add custom logic into the file operation in real time. Note that sbxnam is limited to a maximum of six characters, e.g. SBX:AROPEN. In the case of the LOGFIL:fspec handler, A-Shell uses its own built-in logic to output information about the event to the specified file, allowing you to process the log file later. Each type of hook is described in greater detail in the sections that follow.

For opcode 6 (HOOKOP_APPEVENT), the handler parameter may be used to pass an arbitrary string to the handler previously set up by opcode 2. Typically this may be used to send a contextual message to the handler, such as "starting check run" or "posting run complete".

events  (B,4)  [in]

a bit-field of events to hook, from the following (defined in ashinc:hook.def):

Symbol

Value

Meaning

HFE_PRE_OPEN

&h00000001

prior to open

HFE_POST_OPEN

&h00000002

after open

HFE_PRE_CLOSE

&h00000004

prior to close

HFE_POST_CLOSE

&h00000008

after close

HFE_PRE_READ

&h00000010

prior to read or get (any)

HFE_POST_READ

&h00000020

after read or get (any)

HFE_PRE_READL

&h00000040

prior to readl or getl

HFE_POST_READL

&h00000080

after readl or getl

HFE_PRE_WRITE

&h00000100

prior to write (or update'record)

HFE_POST_WRITE

&h00000200

after write (or update'record)

HFE_PRE_WRITEL

&h00000400

prior to writel (or create'record)

HFE_POST_WRITEL

&h00000800

after writel (or create'record)

HFE_PRE_ALLOC

&h00002000

prior to allocate

HFE_POST_ALLOC

&h00004000

after allocate

HFE_PRE_KILL

&h00008000

prior to kill

HFE_POST_KILL

&h00010000

after kill

HFE_PRE_SORT

&h00020000

prior to sort

HFE_POST_SORT

&h00040000

after sort

HFE_ISAM_ADD

&h00080000

after ISAM 5 (add); see History

HFE_ISAM_DEL

&h00100000

after ISAM 6 (delete); see History

HFE_PRE_ISAMA_DEL

&h00200000

ISAM-A pre delete'record

HFE_POST_ISAMA_DEL

&h00400000

ISAM-A post delete'record

HFE_APP_EVENT1

&h10000000

custom application event

Definition File: ashinc:hook.def

 

flags  (B,4)  [in]

a bit-field of flags which are passed to the hook routine (as a clue to how the hook should operate), and/or which are used by A-Shell to modify the operation of the hook (from ashinc:hook.def):

Symbol

Value

Meaning

HFF_PROG

&h00000001

include program name

HFF_SBX

&h00000002

include sbx name

HFF_DATA

&h00000004

include copy of data just written (POST_WRITE only)

HFF_DATA_WAS

&h00000008

include copy of data as previously read or written, for comparison with data now being written (POST_WRITE only)

HFF_RECNO

&h00000010

include recno

HFF_TIME

&h00000020

include time

HFF_DATE

&h00000040

include date

HFF_TIMESTAMP

&h00000060

Include timestamp in log for each event

HFF_USER

&h00000080

include user name

HFF_PID

&h00000100

include process id

HFF_AUTO_DEL

&h00001000

auto delete hook on prog exit

HFF_SQZ_ENV

&h00080000

'squeeze' env rec (LOGFIL: hooklogs)

HFF_DATA_WAS_NA

&h00010000

there is no "was" data available to pass to the hook routine in response to the HFF_DATA_WAS flag

HFF_DATA_CHG_ONLY

&h00020000

may be used in conjunction with HFE_POST_WRITE to suppress calling the hook function after the write if the record data hasn't changed.

HFF_SQZ_DATA

&h00100000

'squeeze' data recs (LOGFIL: hooklogs)

Definition File: ashinc:hook.def

 

Note that for the SBX handlers, most of the flags affecting the data that is included in the information passed to handler are ignored. The packet is a fixed size and there is nothing to be gained by blanking out certain fields. The flags which do matter are: HFF_DATA and HFF_DATA_WAS, HFF_DATA_CHG_ONLY, and HFF_AUTO_DEL.

enabled  (Num)  [out]

returns zero or one to indicate if the hook is disabled or enabled.

 

Comments

Hook definitions are not directly affected by file open and close operations. Nor are they affected by termination of the program unless the HFF_AUTO_DEL flag is specified when the hook is established. They are automatically removed by termination of the A-Shell session. So you can add/delete all your file hooks in a common application startup/shutdown program, without making any modifications to the individual programs which operate on the files.

MX_FILEHOOK works with random, ISAM, and ISAM-A files. In the case of ISAM and ISAM-A files, only the data file is hooked.

Example

Use the following pattern to establish a file hook...

    ++include'once ashinc:ashell.def

    ++include'once ashinc:hook.def

 

    define FID_CUST    = 1001            ! file ID for customer file

 

map1 hook'vars

    map2 hook'status,f

    map2 hook'file$,s,40

    map2 hook'fid,b,4

    map2 hook'handler$,s,16

    map2 hook'events,b,4

    map2 hook'flags,b,4

 

hook'file$    = "DSK2:CUST.DAT[100,50]"

hook'fid      = FID_CUST

hook'handler$ = "SBX:MYHOOK"

hook'events   = HFE_POST_OPEN or HFE_POST_WRITE or HFE_POST_WRITEL or HFE_POST_CLOSE or HFE_PRE_ALLOC

hook'flags    = HFF_PROG or HFF_SBX or HFF_RECNO or HFF_TIME or HFF_DATE  &

                or HFF_USER or HFF_DATA or HFF_DATA_WAS

 

xcall MIAMEX, MX_FILEHOOK, HOOKOP_ADD, hook'status, hook'file$, hook'fid, hook'handler$, hook'events, hook'flags

if hook'status < 0 then ? "Error setting hook: ";hook'status

 

After the above code is executed the hook handler (MYHOOK.SBX) will be called after every open, write, writel and close operation on the file DSK2:CUST.DAT[100,50], and also every allocate operation on the file. See the following topic Hook SBX Specification.

The above example could be changed to use the LOGFIL: handler instead, by changing the hook'handler$ assignment to something like:

hook'handler$ = "LOGFIL:APPLOG:FILEIO.LOG

or

hook'handler$ = "LOGFIL:dsk0:audit.log[1,2]

See the following topic, File-Based File Hook Handler, for more details.

 

History

2018 July, A-Shell 6.5.1642:  Added handler LOGFIL: and File-Based File Hook Handler to A-Shell

2015 February, A-Shell 5.1.1402:  Added events HFE_ISAM_ADD and HFE_ISAM_DEL. Note that unlike most of the other file hooks, these don't come in PRE- and POST-flavors. For the ADD hook, the record data supplied to the hook routine (rec parameter) will contain the key rather than the record data. Since ISAM adds are followed by a WRITE statement, you can hook that to get the contents of the record itself. For the DEL hook, the record data of the record being deleted is supplied to the hook routine in the pre'rec parameter. The rec parameter should be ignored. The sample hook program FHOOKTST3.BP and hook subroutine FHOOK1.SBX in EXLIB:[908,50] have been updated to illustrate both hooks.

2011 June, A-Shell 5.1.1221:  Added flag HFF_DATA_CHG_ONLY to suppress calling the hook function after the write if the record data hasn't changed.

2010 December, A-Shell 5.1.1197:  File hook refinement: When there is no "was" data available to pass to the hook routine (in response to the HFF_DATA_WAS flag), A-Shell now sets a new flag, HFF_DATA_WAS_NA in the flags field in the hook environment structure passed to the hook routine. This allows the hook routine to distinguish between an empty prior record and unknown prior record contents. The prior contents of the record can only be supplied to the hook routine if the last record # read is the same record # being written. ashinc:hook.def has been updated with the new flag, and the sample hook routine FHOOK1.BP in EXLIB[908,50] (SBX) has been updated to show testing the flag.

2010 January, A-Shell 5.1.1174:  Routine added to A-Shell