📄 gshare.asm
字号:
; OUTPUT: (ds:si) = MFT address
;
; REGISTERS USED: ALL but ES
; (NOT RESTORED)
;
; LINKAGE: Invoked by: Set_Block, Clr_Block
;
; EXTERNAL Invoke: SLE
; REFERENCES:
;
; NORMAL 'C' clear if no overlap
; EXIT: (ax:bx) = offset of first byte in range
; (cx:dx) = offset of last byte in range
;
; ERROR 'C' set if overlap
; EXIT: 'Z' set if 1-to-1 match
; (di) points to previous lock
;
; CHANGE 04/15/87 - lock only write support
; LOG:
;
;******************* END OF SPECIFICATIONS *************************************
;******************+ START OF PSEUDOCODE +**************************************
;
; START CLP
;
; shuffle arguments
; if valid length
; invoke SLE
; set successful return status
; else
; set error return status
; endif
; return
;
; END CLP
;
;******************+ END OF PSEUDOCODE +**************************************
Procedure CLP,NEAR
mov bx,dx ; shuffle arguments
xchg dx,ax
xchg ax,cx ; (ax:bx) = offset
mov cx,si ; (cx:dx) = length
or si,dx ; see if length is 0
; $if nz,and ; if length is > 0 and ;AC000;
JZ $$IF19
add dx,bx
adc cx,ax ; (cx:dx) = lba+1
; $if nc,or ; no carry is ok ;AC000;
JNC $$LL19
mov si,dx
or si,cx
; $if z ; if !> 0 then ;AC000;
JNZ $$IF19
$$LL19:
sub dx,1 ; (cx:dx) = lba of locked region
sbb cx,0
push cs
pop ds
; (es:di) is sft
push si
mov si,es:[di].sf_mft
push si
mov di,1 ; Find own locks
call SLE
; di points to previous lock record
pop si
pop bp
; $else ; we have an error ;AC000;
JMP SHORT $$EN19
$$IF19:
xor si,si
inc si ; carry unchanged, zero reset
mov ax,error_lock_violation ; assume error
stc
; $endif ; endif - we have an error ;AC000;
$$EN19:
ret
EndProc CLP
BREAK <Chk_Block - See if the specified I/O violates locks>
;******************* START OF SPECIFICATIONS ***********************************
;
; NAME: Chk_Block - check range lock on a file
;
; FUNCTION: Chk_Block is called to interogate the lock status of a
; region of a file.
;
; NOTE: This routine is called for every disk I/O operation
; and MUST BE FAST
;
; INPUT: (ES:DI) points to an SFT structure
; (AL) = 80h - Write operation = 0 - any non write operation
; (CX) is the number of bytes being read or written
; BytPos is a long (low first) offset into the file
; of the I/O
; User_ID = 16-bit user id of issuer
; Proc_ID = 16-bit process id of issuer
; (SS) = DOSData
;
; OUTPUT: CF set according to status and presence of locks (see below)
;
; REGISTERS USED: ALL but ES,DI,CX,DS
; (NOT RESTORED)
;
; LINKAGE: IBMDOS Jump Table
;
; NORMAL 'C' clear if no error
; EXIT:
;
; ERROR 'C' set if error
; EXIT: (ax) = error code
; ('error_lock_violation' if conflicting locks)
;
; CHANGE 04/15/87 - lock only write support
; LOG:
;
;******************* END OF SPECIFICATIONS *************************************
;******************+ START OF PSEUDOCODE +**************************************
;
; START Chk_Block
;
; if shared SFT and
; if locks exist
; invoke SLE
; if lock conflicts occur (error)
; if this is !write operation and
; if a write lock found
; set successfull status
; else
; set error status
; endif
; else no error
; flush stack
; endif
; endif
;
; ret
;
; END Chk_Block
;
;******************+ END OF PSEUDOCODE +**************************************
Procedure Chk_Block,NEAR
ASSUME DS:NOTHING,ES:NOTHING,SS:DOSDATA
write_op equ 080h ; write operation requested ;AN000;
lock_all equ 0h ; lock all specified ;AN000;
; PUSH DS ;ICE
; push bx ;ICE
; push ax ;ICE
; mov bx,0140H ;ICE
; xor ax,ax ;ICE
; mov ds,ax ;ICE
; mov ax,word ptr ds:[bx] ;ICE
; mov word ptr ds:[bx],ax ;ICE
; pop ax ;ICE
; pop bx ;ICE
; POP DS ;ICE
EnterCrit critShare
; int 3
nop
nop
PUSH ES
PUSH DI
PUSH CX
PUSH DS
cmp es:[di].sf_mft,0
; $if nz,and ; if the file is SHARED and ;AC000;
JZ $$IF22
push cs
pop ds
mov si,es:[di].sf_MFT ; (DS:SI) = address of MFT record
test [si].mft_lptr,-1
; $if nz,and ; if there are locks on this file and ;AC000;
JZ $$IF22
sub cx,1 ; (cx) = count-1
cmc
; $if c ; there are bytes to lock ;AC000;
JNC $$IF22
;; push ax ; preserve type of operation ;AN000;
; DOS passes AL = 80 for writes
; = 00 for reads
mov ax,WORD PTR BytPos+2
mov bx,WORD PTR BytPos ; (ax:bx) = offset
mov dx,cx
sub cx,cx
add dx,bx
adc cx,ax ; (cx:dx) = lba of lock area
sub di,di ; ignore own locks
call SLE
;; pop ax ; recover type of opperation ;AN000;
; upon return DS:SI points to the RLR with the conflict
;; $if c ; if lock conflicts occur - error ;AC000;
; now we must check what type of lock exists
; and the type of operation in progress.
;; cmp al,write_op ; ;AN000;
;; $if ne,and ; if NOT a write operation and ;AN000;
;; cmp [si].rlr_type,rlr_lwr ; ;AN000;
;; $if e ; if write locked (NOT all locked) ;AN000;
;; clc ; then not true conflict - clear error ;AN000;
;; $else ; else it IS a valid conflict ;AC000;
;; stc ; true error - set error status
;; $endif ; endif - a valid conflict ;AC000;
;; $endif ; endif - conflicts ;AC000;
mov ax,error_lock_violation ; assume error
; $endif ; endif - no need to check ;AC000;
$$IF22:
; exit
;
; 'C' and (ax) setup
POP DS
POP CX
POP DI
POP ES
LeaveCrit critShare
ret ; exit
EndProc Chk_Block
BREAK <MFT_get - get an entry from the MFT>
;******************* START OF SPECIFICATIONS ***********************************
;
; MFT_get - get an entry from the MFT
;
; MFT_get is used to return information from the MFT. System utilities
; use this capability to produce status displays.
;
; MFT_get first locates the (BX)'th file in the list (no particular
; ordering is promised). It returns that name and the UID of
; the (CX)'th SFT on that file and the number of locks on that
; file via that SFT.
;
; ENTRY DS:SI point to DPL which contains:
; (dBX) = zero-based file index
; (dCX) = zero-based SFT index
; (SS) = DOSData
; EXIT 'C' clear if no error
; ES:DI buffer is filled in with BX'th file name
; (BX) = user id of SFT
; (CX) = # of locks via SFT
; 'C' set if error
; (ax) = error code
; ('error_no_more_files' if either index is out
; of range)
;
;******************* END OF SPECIFICATIONS *************************************
Procedure MFT_get,NEAR
; int 3
nop
nop
ASSUME DS:NOTHING,ES:NOTHING
EnterCrit critShare
MOV BX,[SI.DPL_BX]
MOV CX,[SI.DPL_CX]
Context ES
MOV DI,OFFSET DOSDATA:OpenBuf
xchg bx,cx ; (cx) = file index
push cs
pop ds
Off SI,mft ; (ds:si) = fwa of OFFSET MFT
; scan forward until next name
mget1: cmp [si].mft_flag,MFLG_FRE
jz mget3 ; is free space
jl mget7 ; is END
; have another name. see if this satisfies caller
jcxz mget4 ; caller is happy
dec cx
mget3: add si,[si].mft_len ; skip name record
JMP SHORT mget1
; we've located the file name.
;
; (bx) = SFT index
; (DS:SI) = MFT entry
; (ES:DI) = address of caller's buffer
mget4: push di
push si ; save table offset
add si,mft_name
mget5: lodsb
stosb ; copy name into caller's buffer
or al,al
jnz mget5
pop si ; (DS:SI) = name record address
xchg bx,cx ; (cx) = SFT chain count
lds di,[si].mft_sptr
mget6: jcxz mget8 ; have reached the SFT we wanted
dec cx
lds di,[di].sf_chain ; get next link
or di,di
jnz mget6 ; follow chain some more
pop di ; (es:di) = buffer address
;** The file or SFT index was too large - return w/ error
mget7: mov ax,error_no_more_files
stc
LeaveCrit critShare
ret
;** We've got the SFT he wants. Lets count the locks
;
; (es:TOS) = buffer address
; (DS:DI) = address of SFT
; (si) = address of mft
mget8: mov ax,[DI].sf_flags
mov dx,ds ; save segment
push cs
pop ds
mov si,[si].mft_lptr ; (DS:SI) = Lock record address
sub cx,cx ; clear counter
mget9: or si,si
jz mget11 ; no more
cmp di,WORD PTR [si].rlr_sptr
jnz mget10
cmp dx,word PTR [si].rlr_sptr+2
jnz mget10
inc cx
mget10: mov si,[si].rlr_next
JMP SHORT mget9
; Done counting locks. return the info
;
; (cx) = count of locks
; (es:TOS) = buffer address
mget11: mov ds,dx
mov bx,[di].SF_UID ; (bx) = UID
pop di
clc
LeaveCrit critShare
ret
EndProc MFT_get
BREAK <ASC - Add SFT to Chain>
;******************* START OF SPECIFICATIONS ***********************************
;
; ASC - Add SFT to Chain
;
; ASC is called to add an SFT to the front of the chain.
;
; ASC checks the file share mode bits on the other SFTs in the chain and
; reports a conflict. The new SFT is NOT ADDED in the case of
; conflicts.
;
; ENTRY (BX) = FBA MFT name record
; (DS:SI) = SFT address
; EXIT 'C' clear if added
; (ds:si) point to sft
; (bx) offset of mft
; 'C' set if conflict
; (ax) = error code
; USES ALL
;
;******************* END OF SPECIFICATIONS *************************************
Procedure ASC,NEAR
cmp [si].sf_MFT,0
jnz asc9 ; already on chain - internal error
; The SFT looks good... lets see if there are any use conflicts
; Message 1,<"Adding sft ">
mov ax,User_ID ; place user information in SFT
mov [si].sf_UID,ax ; do it before CUC (he checks UID)
mov ax,Proc_ID
mov [si].sf_PID,ax
call CUC ; check use conflicts
jc asc8 ; use conflicts - forget it
; MessageNum AX
; MessageNum AX
; Message 1,<" to ">
; MEssageNum DS
; Message 1,<":">
; MessageNum SI
; Message 1,<" ">
mov [si].sf_MFT,bx ; make SFT point to MFT
; MessageNum [si].sf_mft
; Message 1,<13,10>
mov cx,[si].sf_mode ; (cx) = open mode
mov dx,ds ; (dx:si) = SFT address
push cs
pop ds ; (ds:bx) = MFT address
;
; Not special file and no previous sft found OR normal SFT. We link it in
; at the head of the list.
;
; (dx:si) point to sft
; (ds:bx) point to mft
;
les di,[bx].mft_sptr ; get first link
;M003;
; If the SFT to be inserted is the same as the current one, do not link it in
;
mov ax,es ;M003
cmp si,di ;Offsets same? ;M003
jne asc_ins ;No, link in ;M003
cmp ax,dx ;Segments same? ;M003
je asc75 ;Yes, do not insert ;M003
asc_ins:
mov word ptr [bx].mft_sptr,si ; link in this sft
mov word ptr [bx].mft_sptr+2,dx ; link in this sft
mov ds,dx
mov word ptr [si].sf_chain,di
mov word ptr [si].sf_chain+2,es
asc75: mov ds,dx ; point back to sft
clc
asc8: ret
; the SFT is already in use... internal error
asc9: push ax
off ax,AscErr
call INTERR ; NEVER RETURNS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -