⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gshare.asm

📁 DOS 源代码 系列之 command 源码
💻 ASM
📖 第 1 页 / 共 5 页
字号:
;  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 + -