Files
Digital-Research-Source-Code/MPM OPERATING SYSTEMS/MPM-86/MPM-86 2.0 SOURCES/01/FILE2.BDO
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

1319 lines
36 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;*************************** bdos file system part 2 *****************
;
scndm:
;scan the disk map addressed by dptr for non-zero
;entries, the allocation vector entry corresponding
;to a non-zero entry is set to the value of cl (0,1)
;bx addresses the beginning of the directory entry
;
call getdptra ;bx = buffa + dptr
add bx,dskmap ;bx = diskmap address
push cx ;save the 0/1 bit to set
mov cl,fcblen-dskmap+1 ;size of single byte diskmap+1
scndm0:
;loop for each diskmap entry
pop dx ;recall bit parity
dec cl
jnz $+3
ret
;all done scanning?
;no, get next entry for scan
push dx ;replace bit parity
cmp single,0
jz scndm1
;single byte scan operation
push cx ;save counter
push bx ;save map address
mov cl,[bx]
mov ch,0 ;cx=block#
jmps scndm2
scndm1:
;double byte scan operation
dec cl ;count for double byte
push cx ;save counter
mov cx,[bx] ;cx=block
inc bx
push bx ;save map address
scndm2:
;arrive here with cx=block#,
;dl= 0/1
or cx,cx ;skip if = 0000
jz scan3
mov bx,maxall ;check invalid index
cmp bx,cx
jnae $+5
call setallocbit
;
;bit set to 0/1
scan3: ;
pop bx
inc bx ;to next bit position
pop cx ;recall counter
jmps scndm0 ;for another item
;
GET_NALBS:
;GET # OF ALLOCATION VECTOR BYTES
mov bx,maxall
mov cl,3 ;perform maxall/8
shr bx,cl
inc bx
RET8A: RET
if MPM
TEST_DIR:
CALL HOME
CALL SET_END_DIR
TEST_DIR1:
MOV CL,0FEH
CALL RD_DIR
CMP FLUSHED,FALSE
JNE RET8A
CALL END_OF_DIR
JZ RET8A
JMP TEST_DIR1
endif
initialize:
;initialize the current disk
;lret = false ;set to true if $ file exists
;compute the length of the allocation vector - 2
if MPM
MOV DX,TLOG
CALL TEST_VECTOR ;IS TLOG(CURDSK) ON
JZ INITIALIZE1 ;NO
MOV BX,TLOG ;TLOG(CURDSK) = OFF
CALL REMOVE_DRIVE
MOV TLOG,BX
MOV FLUSHED,FALSE
MOV CH,1 ;IS A FILE CURRENTLY OPEN
CALL SEARCH_OLIST ;ON THIS DRIVE?
JNZ INITIALIZE1 ;NO - RELOG IN THE DRIVE
CALL TEST_DIR ;HAS A CHANGE IN MEDIA OCCURRED?
JZ RET8A ;NO - DO NOT RELOG IN DRIVE
INITIALIZE1: ;LOG IN DRIVE
endif
CALL GET_NALBS ;BX = # OF ALLOCATION VECTOR BYTES
mov cx,bx
mov bx,alloca ;base of allocation vector
;fill the allocation vector
;with zeros
init0:
mov b[bx],0
inc bx ;alloc(i)=0
loop init0
;set the reserved space for
;the directory
MOV BX,DRVLBLA ;ZERO DIRECTORY LABEL DATA BYTE
MOV B[BX],0
mov dx,dirblk
mov bx,alloca ;bx=.alloc()
mov [bx],dx ;sets reserved directory blks
;allocation vector initialized
call home ;home disk
;cdrmax = 3 (scans at least
;one directory record)
mov bx,cdrmaxa
mov w[bx],3
;cdrmax = 0000
call setenddir ;dcnt = enddir
;read directory entries and
;check for allocated storage
init2:
mov cl,true
call rddir
call endofdir
jz ret8b ;rz
;not end of directory,
;valid entry ?
call getdptra ;bx = buffa + dptr
cmp b[bx],empty
jz init2 ;go get another item
;not empty,user code the same?
CMP B[BX],20H ;IS ENTRY DIRECTORY LABEL ?
JE DRV_LBL ;YES
TEST B[BX],70H ;IS ENTRY SPECIAL TYPE OF FCB ?
JNZ INITIAL3 ;YES
;now scan the disk map for
;allocated blocks
mov cl,1 ;set to allocated
call scndm
INITIAL3:
call setcdr ;set cdrmax to dcnt
jmps init2 ;for another entry
DRV_LBL:
MOV AL,EXTNUM[BX]
MOV BX,DRV_LBLA
MOV [BX],AL
JMPS INITIAL3
;
cpydirloc:
;copy directory location to lret following
;delete, rename, ... ops
mov al,dirloc
jmp staret
; ret
;
compext:
;compare extent# in al with that in cl, return nonzero
;if they do not match
push cx ;save cl's original value
mov ch,extmsk
not ch
;ch has negated form of
;extent mask
and cl,ch ;low bits removed from cl
and al,ch ;low bits removed from al
sub al,cl
and al,maxext ;set flags
pop cx ;restore original values
ret8b: ret
;
GET_DIR_EXT:
;COMPUTE DIRECTORY EXTENT FROM FCB
;SCAN FCB DISK MAP BACKWARDS
;UPON RETURN BX = .FCB(EXT), AL = DIR EXT
; DL IS NON-ZERO IF NO BLOCKS FOUND
;
CALL GTFCBA ;BX = .FCB(VRECORD)
MOV DX,1000H ;DH = DISK MAP POSITION (REL TO 1)
;DL = NO BLOCKS SWITCH
GET_DE1:
DEC DH
DEC BX ;DECREMENT DISK MAP PTR
CMP B[BX],0 ;IS DISK MAP BYTE NON-ZERO ?
JNE GET_DE2 ;YES
OR DH,DH ;NO - CONTINUE SCAN
JNE GET_DE1
DEC DL ;DL NON-ZERO IF NO BLOCKS FOUND
GET_DE2:
CMP SINGLE,TRUE ;ARE DISK BLOCK INDEXES SINGLE BYTE ?
MOV AL,DH ;AL = BLOCK OFFSET IN DISK MAP
JZ GET_DE3 ;YES
SHR AL,1 ;DIVIDE BLOCK OFFSET BY 2
;AL = LAST NON-ZERO BLOCK INDEX IN FCB (REL TO 0)
;COMPUTE EXT OFFSET FROM LAST NON-ZERO BLOCK INDEX BY
;SHIFTING BLOCK INDEX RIGHT 7-BLKSHF
GET_DE3:
XOR AH,AH
MOV CL,7
SUB CL,BLKSHF
SHR AX,CL ;AL = EXT OFFSET
MOV AH,EXTMSK ;IF EXT OFFSET > EXTMSK THEN
CMP AH,AL ; CONTINUE SCAN
JB GET_DE1
;DIR EXT = (FCB EXT & (~EXTMSK) & MAXEXT) | EXT OFFSET
CALL GETEXTA ;BX = .FCB(EXT)
MOV CL,[BX] ;CL = FCB EXTENT VALUE
NOT AH ;AH = ~EXTMSK
AND AH,MAXEXT ;AH = AH & MAXEXT
AND AH,CL ;AH = AH & FCB EXTENT
OR AL,AH ;AL = DIR EXT
RET ;DL NON-ZERO IF NO BLOCKS FND
SEARCHI:
;SEARCH INITIALIZATION
MOV BX,INFO
MOV SRCHA,BX ;SEARCHA = INFO
SEARCHI1:
MOV DIRLOC,0FFH ;CHANGED IF ACTUALLY FOUND
MOV SRCHL,CL ;SEARCHL = CL
RET
SEARCH:
srch:
;search for directory element
;of length CL at INFO
CALL SEARCHI;
SEARCH1: ;ENTRY POINT USED BY RENAME
call setenddir ;dcnt = enddir
call home ;to start at the beginning
;(drop through to searchn)
;
SEARCHN:
srchn:
;search for the next directory element, assuming
;a previous call on search which sets searcha and searchhl
if MPM
MOV BX,OFFSET USER_ZERO_PASS
TEST B[BX],TRUE
JZ SRCHN1 ;IF USER_ZERO_PASS THEN DO;
MOV B[BX],FALSE ; USER_ZERO_PASS = FALSE;
CALL SWAP ; CALL SWAP:
; END;
SRCHN1:
endif
if CPM
MOV USER_ZERO_PASS,FALSE
endif
mov cl,false
call rddir ;read next dir element
call endofdir
jz srchfin
;skip to end if so
;not end of directory,
;scan for match
mov dx,srcha ;dx=beginning of user fcb
mov si,dx
lods al ;first character
cmp al,empty ;keep scanning if empty
jz srchnext
;not empty, may be end of
;logical directory
push dx ;save search address
call compcdr ;past logical end?
pop dx ;recall address
jnb srchfin
;artificial stop
srchnext:
call getdptra ;bx = buffa+dptr
MOV CL,SRCHL ;LENGTH OF SEARCH TO CL
XOR CH,CH ;ch counts up, cl counts down
CMP B[BX],EMPTY ;IS DIR FCB EMPTY
JNZ $+5 ;NO
CALL SAVE_DCNT_POS1 ;YES - SAVE DCNT
MOV SAVE_XFCB,FALSE
MOV AL,[BX] ;IS FCB AN XFCB ?
AND AL,11101111B
CMP AL,[BX]
JE SRCH_LOOP ;NO
MOV SI,DX
CMP AL,[SI] ;DOES USER # MATCH ?
JNZ SRCH_LOOP ;NO
TEST FIND_XFCB,TRUE ;IS FIND_XFCB TRUE ?
JZ SEARCH_N ;NO
MOV SAVE_XFCB,TRUE ;
JMPS SRCHOK
srchfin:
;end of directory, or empty name
CALL SAVE_DCNT_POS1
call setenddir ;may be artifical end
LRET_EQ_FF:
mov al,255
MOV CH,AL
INC CH ;ZERO FLAG SET ON UNSUCCESSFUL
jmp staret ;SEARCHES
srchloop:
or cl,cl
jz endsearch
mov si,dx
lods al ;FCB CHARACTER
cmp al,'?'
jz srchok ;? matches all
;scan next character if not
;ubytes
cmp ch,ubytes
jz srchok
;not the ubytes field,
;extent field
cmp ch,extnum ;may be extent field
jz srchext ;skip to search extent
CMP CH,MODNUM ;IS FIELD MODULE # ?
JNZ $+4 ;NO
AND AL,3FH ;YES - MASK OFF HIGH ORDER BITS
sub al,[bx]
and al,7fh ;mask-out flags/extent modulus
JNZ SEARCHNM
jmps srchok ;matched character
srchext:
;a has fcb character
;attempt an extent # match
if MPM
CMP BYTE PTR SDCNT+1,TRUE ;IF SDCNT+1 = FF THEN DO;
JNE DONT_SAVE ; SDCNT = DCNT
MOV SI,DCNT ; SDBLK = DBLK
MOV SDCNT,SI ; END;
MOV SI,DBLK
MOV SDBLK,SI
DONT_SAVE:
endif
push cx ;save counters
mov cl,[bx] ;directory character to c
call compext ;compare user/dir char
pop cx ;recall counters
LAHF ;SAVE COMPEXT RESULT
TEST USER_ZERO_PASS,TRUE
JNZ SAVE_DCNT_POS2 ;IF USER0_PASS GO TO SAVE_DCNT_POS2
;DISABLE SEARCH UNDER USER ZERO IF ANY FCB IS FOUND UNDER
;THE CURRENT USER NUMBER
MOV SEARCH_USER0,FALSE
MOV FCB_EXISTS,TRUE
SAHF
JNZ SEARCHN_JMP ;skip if no match
srchok:
;current character matches
inc dx
inc bx
inc ch
dec cl
jmps srchloop
endsearch:
;entire name matches, return dir position
TEST SAVE_XFCB,TRUE ;IS SAVE_XFCB TRUE
JZ ENDSEARCH1 ;NO
CMP BYTE PTR XDCNT+1,0FEH ;IF XDCNT+1 = FE THEN
JNE SEARCHN_JMP ; CALL SAVE_DCNT_POS
CALL SAVE_DCNT_POS
SEARCHN_JMP:
JMP SEARCHN
ENDSEARCH1:
MOV DIRLOC,0
mov al,ldcnt
and al,dskmsk
mov lret,al
MOV CH,AL
INC CH ;ZERO FLAG RESET ON SUCCESSFUL
ret9: ret ;SEARCHES
SEARCHNM: ;SEARCH NO MATCH ROUTINE
OR CH,CH ;FCB(0) ?
JNZ SEARCHN_JMP ;NO
TEST B[BX],0FFH ;IS DIR FCB(0) = 0 ?
JNZ SEARCHN_JMP ;NO
TEST SEARCH_USER0,TRUE ;IS SEARCH_USER0 TRUE
JZ SEARCHN_JMP
MOV USER_ZERO_PASS,TRUE
if MPM
CALL SWAP
endif
JMPS SRCHOK
if MPM
SWAP: ;SWAP SDCNT,SDBLK WITH SDCNT0,SDBLK0
MOV AX,SDCNT
XCHG AX,SDCNT0
MOV SDCNT,AX
MOV AX,SDBLK
XCHG AX,SDBLK0
MOV SDBLK,AX
RET
endif
;
SAVE_DCNT_POS2:
;SAVE DIRECTORY POSITION OF MATCHING FCB
;UNDER USER ZERO WITH MATCHING EXTENT & MODNUM = 0
SAHF
JNE SEARCHN_JMP
INC BX
CMP B[BX],0
JNE SEARCHN_JMP
CALL SAVE_DCNT_POS
JMP SEARCHN
SAVE_DCNT_POS1:
CMP BYTE PTR XDCNT+1,0FFH
JNE RET9
SAVE_DCNT_POS:
MOV SI,DCNT
MOV XDCNT,SI
MOV SI,DBLK
MOV XDBLK,SI
RET
;
INIT_XFCB_SEARCH:
MOV AL,0FFH
INIT_XFCB_SEARCH1:
MOV FIND_XFCB,AL ;FIND_XFCB = FFH
MOV AL,0FEH
MOV BYTE PTR XDCNT+1,AL ;XDCNT+1 = FEH
RET
;
DOES_XFCB_EXIST:
CMP BYTE PTR XDCNT+1,0FEH ;IF XDCNT+1 = FEH THEN RETURN
JE RET9
CALL SET_DCNT_DBLK ;DCNT,DBLK = XDCNT,XDBLK - 1
XOR AL,AL
CALL INIT_XFCB_SEARCH1
MOV BX,SRCHA ;OF 10H INTO FCB(0)
OR B[BX],10H
MOV CL,EXTNUM
CALL SEARCHI1 ;SEARCH FOR XFCB
JMP SEARCHN ;Z FLAG SET IF UNSUCCESSFUL
;
;
delet:
;delete the currently addressed file
call checkwrite ;write protected?
CALL CHK_PWS ;CHECK FOR PASSWORD ERROR
PUSHF ;SAVE RESULT FOR LATER
CALL GET_ATTS ;GET & SAVE FCB ATTRIBUTES
MOV ATTRIBUTES,AL
CALL INIT_XFCB_SEARCH ;SAVE DCNT OF 1ST XFCB IN SEARCH
;PASS
MOV CL,EXTNUM ;SEARCH FOR FILE
CALL SEARCH
POP AX ;IGNORE PASSWORD ERROR IF NO FILES
JZ DELETE2 ;FOUND, DELETE XFCBS
MOV AH,AL
SAHF
JZ $+5
JMP CHK_PW1 ;PASSWORD ERROR
MOV AL,ATTRIBUTES ;IF DELETING XFCBS ONLY, A PASS
RCL AL,1 ;THROUGH THE ENTIRE DIRECTORY
JB DELETE015 ;IS REQUIRED TO LOCATE XFCBS
MOV BX,INFO ;EACH DCNT MUST BE VERIFIED (MP/M)
CALL CHK_WILD ;AND EACH FCB MUST BE CHECKED FOR
JZ DELETE015 ;READ/ONLY ON WILD CARD DELETES
if MPM
CALL TST_OLIST ;VERIFY DCNT AGAINST OPEN LIST
endif
CALL CK_RODIR ;ONLY ONE PASS IS REQUIRED ON
JMPS DELET0 ;NORMAL NON-WILD DELETES
DELETE01:
;LOOP WHILE DIRECTORY MATCHES
JZ DELETE02
DELETE015:
if MPM
CALL TST_OLIST ;VERIFY DCNT AGAINST OPEN LIST
endif
CALL CK_RODIR ;VERIFY FCB IS NOT READ/ONLY
CALL SEARCHN
JMPS DELETE01
DELETE02:
MOV AL,ATTRIBUTES ;SKIP DELETE OF FCBS IF ATTRIBUTE
RCL AL,1 ;F5' IS SET
JB DELETE2
mov cl,extnum
call srch ;search through file type
delet0:
;loop while directory matches
JZ DELETE2
DELETE1:
;set each non zero disk map
;entry to 0
;in the allocation vector
if MPM
CALL CHK_OLIST ;REMOVE MATCHING OPEN LIST ITEMS
endif
call getdptra ;bx=.buff(dptr)
TEST B[BX],10H
mov b[bx],empty
mov cl,0
JNZ $+5 ;DONT FREE BLOCKS FOR XFCBS
call scndm ;alloc elts set to 0
call wrdir ;write the directory
call srchn ;to next element
jmps delet0 ;for another record
DELETE2:
CALL DOES_XFCB_EXIST ;IF XFCBS EXIST, DELETE THEM ON
JNZ DELETE1 ;ANOTHER PASS THROUGH THE DIRECTORY
JMP CPY_DIR_LOC
;
getblock:
;given allocation vector position cx, find the zero bit
;closest to this position by searching left and right.
;if found, set the bit to 1 and return the bit position
;in bx. if not found (i.e., we pass 0 on the left, or
;maxall on the right), return 0000 in bx
;
mov dx,cx ;copy start pos. to dx
lefttst:
or cx,cx
jz righttst ;skip if left=0000
;left not at position zero,
;bit zero ?
dec cx
push dx
push cx ;left,right pushed
call getallocbit
rcr al,1
jae rblok ;return block number if zero
;bit is one, so try the right
pop cx
pop dx ;left, right restored
righttst:
cmp dx,maxall ;value of maximum allocation#
jae rblok0 ;return block 0000 if so
inc dx
push cx
push dx ;left, right pushed
mov cx,dx ;ready right for call
call getallocbit
rcr al,1
jae rblok ;return block number if zero
pop dx
pop cx ;restore left and right ptr
jmps lefttst ;for another attempt
rblok:
rcl al,1
inc al ;bit back into position
;and set to 1
;dl contains the number of
;shifts required to reposition
call rotr ;move bit back to position
;and store
pop bx
pop dx ;bx returned value,
;dx discarded
ret
rblok0:
;cannot find an available
;bit, return 0000
or cx,cx
jnz lefttst
mov bx,0000h
ret
;
;copyfcb:
; ;copy the entire fcb
; mov cl,0
; mov dl,fcblen ;start at 0, to fcblen-1
; ; jmp copydir
;
copy_dir:
;copy fcb information starting
;into the currently addressed directory entry
MOV DH,80H ;DH = ATTRIBUTE MASK
COPY_DIR0:
CALL COPY_DIR2 ;INIT REGS BX, CX, DX FOR COPY
INC CL
COPY_DIR1:
DEC CL
JZ SEEK_COPY ;COPY OPERATION COMPLETE
MOV AH,[BX] ;PICK UP DIR FCB BYTE
AND AH,CH ;MASK WITH ATTRIBUTE MASK (0 | 80H)
MOV SI,DX
LODS AL ;PICK UP FCB BYTE
AND AL,7FH ;CLEAR ATTRIBUTE BIT
OR AL,AH ;OR IN DIR FCB ATT & ATT MASK
MOV [BX],AL ;STORE IN DIR FCB BYTE
INC BX ;ADVANCE FCB PTR
INC DX ;ADVANCE DIR FCB PTR
JMPS COPY_DIR1
COPY_DIR2:
push dx ;save length for later
mov ch,0 ;double index to cx
mov dx,info ;bx = source for data
add dx,cx ;dx=.fcb(cl), source for copy
call getdptra ;bx=.buff(dptr), destination
pop cx ;dx=source, bx=dest, c=length
RET
seekcopy:
;enter from close to seek and copy current element
call seekdir ;to the directory element
jmp wrdir ;write the directory element
;ret
CHECK_WILD:
;CHECK FOR ? IN FILE NAME OR TYPE
MOV BX,INFO
CHECK_WILD0: ;ENTRY POINT USED BY RENAME
CALL CHK_WILD
JNZ RET10
MOV AL,9 ;EXTENDED ERROR 9
JMP SET_ARET
CHK_WILD:
;CHECK FCB FOR ? MARKS
;ON ENTRY BX = .FCB(0)
;ON EXIT Z FLAG ON INDICATES ? MARK FOUND
MOV CX,3F0BH ;CH = 3F, CL = 11
CHK_WILD1:
INC BX ;ADVANCE FCB PTR
MOV AL,CH
SUB AL,[BX]
AND AL,CH
JZ RET10 ;RTN WITH Z FLAG SET IF ? FND
DEC CL
JNZ CHK_WILD1
OR AL,AL ;RTN WITH Z FLAG RESET - NO ?S
RET
COPY_USER_NO:
MOV BX,INFO ;FCB(16) = FCB(0)
MOV AL,[BX]
ADD BX,DSKMAP
MOV [BX],AL ;BX = .FCB(16)
RET
rename:
;rename the file described by the first half of
;the currently addressed file control block. the
;new name is contained in the last half of the
;currently addressed file conrol block. the file
;name and type are changed, but the reel number
;is ignored. the user number is identical.
;
call checkwrite ;may be write protected
CALL CHECK_WILD ;CHECK FOR ?S IN 1ST FILENAME
CALL CHK_PASSWORD ;CHECK PASSWORD
CALL INIT_XFCB_SEARCH
CALL COPY_USER_NO ;FCB(16) = FCB(0)
MOV SRCHA,BX
CALL CHECK_WILD0 ;CHECK 2ND FILENAME FOR ?S
MOV CL,EXTNUM ;CHECK TO SEE IF NEW FILENAME
CALL SEARCHI1 ;ALREADY EXIST ON DRIVE
CALL SEARCH1
JZ $+5
JMP FILE_EXISTS ;ERROR - FILE EXISTS
CALL DOES_XFCB_EXIST ;DELETE XFCB IF PRESENT
JZ $+5
CALL DELETE1
CALL COPY_USER_NO ;FCB(16) = FCB(0) AGAIN
CALL INIT_XFCB_SEARCH
;search up to the extent field
mov cl,extnum
call srch
; ;copy position 0
; mov bx,info
; mov al,[bx] ;bx=.fcb(0), a=fcb(0)
; add bx,dskmap ;bx=.fcb(diskmap)
; mov [bx],al ;fcb(dskmap)=fcb(0)
; ;assume the same disk
; ;for new named file
JNZ $+3
RET10: RET
CALL CK_RODIR ;CHECK FOR READ/ONLY FILE
if MPM
CALL CHK_OLIST
endif
renam0:
;not end of directory,
;rename next element
mov cl,dskmap
mov dl,extnum
call copydir
;element renamed, move to next
call srchn
JNZ RENAM0
RENAME1:
CALL DOES_XFCB_EXIST ;RENAME XFCB IF PRESENT
JNZ $+5
JMP CPY_DIR_LOC
CALL COPY_USER_NO ;XFCB(16) = XFCB(0)
JMPS RENAM0
;
indicators:
;set file indicators for current fcb
CALL GET_ATTS
mov cl,extnum
call srch ;through file type
JZ RET10
if MPM
CALL CHK_OLIST
endif
indic0:
;not end of directory,
;continue to change
mov cl,0
mov dl,extnum ;copy name
CALL COPY_DIR2
CALL MOVE
CALL SEEK_COPY
call srchn
JNZ INDIC0
JMP CPY_DIR_LOC
;
open:
;search for the directory entry, copy to fcb
mov cl,namlen
call srch
OPEN1:
jz ret10 ;return with lret=255 if end
;not end of directory,copy fcb
opencopy:
;(referenced below to copy fcb
CALL SETFWF ;AL = MODNUM | FWFMSK
PUSH BX ;BX = .FCB(MODNUM)
DEC BX
DEC BX
MOV AH,[BX] ;AH = EXTNUM
push ax ;SAVE EXTNUM & MODNUM
call getdptra
xchg bx,dx ;dx = .buff(dptr)
mov bx,info ;bx=.fcb(0)
mov cl,nxtrec ;length of move operation
push dx ;save .buff(dptr)
call move ;from .buff(dptr) to .fcb(0)
;note that entire fcb is
;copied, including indicators
call setfwf ;sets file write flag
pop dx
mov bx,extnum
add bx,dx ;bx=.buff(dptr+extnum)
mov cl,[bx]
; mov bx,reccnt
; add bx,dx
; mov ch,[bx]
POP AX
POP BX
MOV [BX],AL ;RESTORE MODNUM
DEC BX
DEC BX
MOV [BX],AH ;RESTORE EXTNUM NUMBER
;
;bx = .user extent#, ch = dir rec cnt, cl = dir extent#
;if user ext < dir ext then user := 128 records
;if user ext = dir ext then user := dir records
;if user ext > dir ext then user := 0 records
;
; cmp cl,[bx]
; mov al,ch ;ready dir reccnt
; jz openrcnt ;if same, user gets dir reccnt
; mov al,0
; jb openrcnt ;user is larger
; mov al,128 ;directory is larger
;openrcnt: ;a has record count to fill
; mov bx,info
; mov dx,reccnt
; add bx,dx
; mov [bx],al
;ret11: ret
;BX = .USER EXTENT #, CL = DIR EXTENT #
SET_RC:
MOV CH,0
LEA SI,(RECCNT-EXTNUM)[BX]
MOV AL,[BX] ;AL = CURRENT EXTENT
CMP AL,CL ;COMPARE FCB EXT TO DIR EXT
JZ SET_RC2 ;FCB EXT = DIR EXT
; ACTUAL_RC = 0, FCB(RC) = FCB(RC)
MOV AL,0
JAE SET_RC1 ;FCB EXT > DIR EXT
; ACTUAL_RC = 0, FCB(RC) = 0
MOV AL,128 ;FCB EXT < DIR EXT
MOV CH,[SI] ; ACTUAL_RC = FCB(RC), FCB(RC) = 128
SET_RC1:
MOV [SI],AL
SET_RC2:
MOV ACTUAL_RC,CH
RET11: RET
mergezero:
;bx = .fcb1(i), dx = .fcb2(i),
;if fcb1(i) = 0
;then fcb1(i) := fcb2(i)
cmp w[bx],0
jnz ret11 ;rnz
mov si,dx
lods ax
mov [bx],ax
ret12: ret
;
RESTORE_RC:
;BX = .FCB(EXTNUM)
;IF ACTUAL_RC ~= 0 THEN FCB(RC) = ACTUAL_RC
MOV AL,ACTUAL_RC
OR AL,AL
JZ RET12
LEA SI,(RECCNT-EXTNUM)[BX]
MOV [SI],AL
RET
close:
;locate the directory element and re-write it
xor ax,ax
mov lret,al
if MPM
MOV DONT_CLOSE,AL
endif
; mov dcnt,ax
call nowrite
jnz ret12 ;skip close if r/o disk
;check file write flag -
;0 indicates written
call getmodnum ;fcb(modnum) in a
and al,fwfmsk
jnz ret12 ;return if bit remains set
CLOSE1:
MOV COMP_FCB_CKS,TRUE
CALL GETEXTA
MOV AL,[BX]
MOV SAVE_EXT,AL ;SAVE EXTENT
CALL CLOSE_FCB
CALL GETDPTRA
MOV CL,EXTNUM[BX] ;CL = DIR EXTENT
CALL GETEXTA
MOV AL,SAVE_EXT ;RESTORE EXTENT
MOV [BX],AL
JMP SET_RC
CLOSE_FCB:
CALL GET_DIR_EXT ;BX = .FCB(EXT), AL = DIR EXT
;DL NON-ZERO INDICATES NO BLOCKS
;EXIST IN FCB
MOV CH,[BX] ;SAVE CURRENT EXTENT
MOV [BX],AL ;FCB(EXT) = DIR EXT
INC AL
CMP CH,AL ;DID ORIGINAL FCB(EXT) = DIR EXT + 1 ?
JNE CLOSE2 ;NO
OR DL,DL ;DO ALLOCATED BLOCKS EXIST IN FCB ?
JNZ CLOSE2 ;NO
LEA SI,(RECCNT-EXTNUM)[BX]
CMP B[SI],0 ;IS FCB(RC) = 0
JNZ CLOSE2 ;NO
MOV B[SI],80H ;SET FCB(RC) TO 128
CLOSE2:
CALL RESTORE_RC ;RESTORE FCB(RC)
mov cl,namlen
call srch ;locate file
; call endofdir
jz ret12 ;return if not found
;merge the disk map at info
mov cx,dskmap
call getdptra
add bx,cx
xchg bx,dx ;dx is .buff(dptr+16)
mov bx,info
add bx,cx ;dx=.buff(dptr+16),
;bx=.fcb(16)
mov cl,(fcblen-dskmap) ;length of single byte dm
merge0:
cmp single,0
jz merged ;skip to double
;
;this is a single byte map
;if fcb(i) = 0 then fcb(i) = buff(i)
;if buff(i) = 0 then buff(i) = fcb(i)
;if fcb(i) <> buff(i) then error
;
mov al,[bx]
or al,al
mov si,dx
lods al
jnz fcbnzero
;fcb(i) = 0
mov [bx],al ;fcb(i) = buff(i)
fcbnzero:
or al,al
jnz buffnzero
;buff(i) = 0
mov al,[bx]
mov di,dx
cld
stos al ;buff(i)=fcb(i)
buffnzero:
cmp al,[bx]
jnz mergerr ;fcb(i) = buff(i)?
jmps dmset ;if merge ok
merged:
;this is a double byte merge
call mergezero ;buff = fcb if buff 0000
xchg bx,dx
call mergezero
xchg bx,dx ;fcb = buff if fcb 0000
;they should be identical
;at this point
mov si,dx
mov ax,[si]
cmp ax,[bx]
jnz mergerr
inc dx
inc bx
;merge ok for this pair
dec cl ;extra count for double byte
dmset:
inc dx
inc bx
dec cl
jnz merge0 ;for more
;end of disk map merge,
;check record count
;dx = .buff(dptr)+32,
;bx = .fcb(32)
mov cx,-(fcblen-extnum)
add bx,cx
xchg bx,dx
add bx,cx
;dx = .fcb(extnum),
;bx = .buff(dptr+extnum)
mov si,dx
lods al ;current user extent number
;if fcb(ext) >= buff(fcb) then
;buff(ext) := fcb(ext),
;buff(rec) := fcb(rec)
cmp al,[bx]
jb endmerge
if MPM
LAHF
endif
;fcb extent number >=
;dir extent number
mov [bx],al ;buff(ext) = fcb(ext)
;update dir. rec count field
mov cx,(reccnt-extnum)
add bx,cx
xchg bx,dx
add bx,cx
;dx=.buff(reccnt),
;bx=.fcb(reccnt)
if MPM
;UNDER MP/M RECCNT MAY HAVE BEEN EXTENDED
;BY ANOTHER PROCESS - IF EXTENTS MATCH, SET
;BOTH RECCNT FIELDS TO THE HIGHER VALUE
SAHF
JNZ DMSET1
MOV SI,DX
MOV AL,[SI]
CMP AL,[BX]
JB DMSET1
MOV [BX],AL
DMSET1:
endif
mov al,[bx]
mov di,dx
stos al ;buff(reccnt)=fcb(reccnt)
endmerge:
if MPM
TEST DONT_CLOSE,TRUE
JNZ RET13
endif
;SET T3' OFF INDICATING FILE UPDATE
CALL GETDPTRA
ADD BX,11
MOV AL,[BX]
AND AL,7FH
MOV [BX],AL
CALL SETFWF
; mov fcbcopied,true ;mark as copied
jmp seekcopy ;ok to "wrdir" here -
;1.4 compatible
; ret
mergerr:
CALL MAKE_FCB_INV
;elements did not merge ok
dec lret ;=255 non zero flag set
ret13: ret
SET_DCNT_DBLK:
MOV BX,XDCNT
AND BL,0FCH
DEC BX
MOV DCNT,BX
MOV BX,XDBLK
MOV DBLK,BX
RET
if MPM
SDCNT_EQ_XDCNT:
MOV BX,OFFSET SDCNT
MOV DX,OFFSET XDCNT
MOV CL,4
JMP MOVE
endif
;
make:
;create a new file by creating a directory entry
;then opening the file
CMP XDCNT,0FFFFH
JNE $+5
JMP LRET_EQ_FF
CALL SET_DCNT_DBLK
call checkwrite ;may be write protected
push info
mov info,offset efcb ;info = .empty
mov cl,1
CALL SEARCHI
CALL SEARCHN
;zero flag set if no space
pop info ;recall word ptr info address
jz ret13 ;return with error condition
;255 if not found
TEST MAKE_XFCB,0FFH ;RETURN EARLY IF MAKING AN XFCB
JNZ RET13
MOV BX,INFO
ADD BX,13
MOV B[BX],0 ;CLEAR S1 BYTE
INC BX
MOV AL,[BX] ;CLEAR AND SAVE FILE WRITE FLAG
PUSH AX
PUSH BX
AND B[BX],3FH
INC BX
;clear the remainder of fcb
mov cl,fcblen-namlen ;number of bytes to fill
xor al,al ;clear al for fill
make0:
mov [bx],al
inc bx
dec cl
jnz make0
call setcdr ;may have extended dir
;now copy entry to dir
MOV CL,0
MOV DX,FCBLEN ;DH = 0
CALL COPY_DIR0
POP BX ;RESTORE FILE WRITE FLAG
POP AX
MOV [BX],AL
MOV ACTUAL_RC,0 ;ACTUAL_RC = 0
;set file write flag to "1"
jmp setfwf
;ret
;
openreel:
;close the current extent, and open the next one
;if possible. rmf is true if in read mode.
; xor al,al
; mov fcbcopied,al ;set true if actually copied
CALL GETMODNUM
MOV SAVE_MOD,AL ;SAVE CURRENT MODULE #
CALL GETEXTA
MOV AL,[BX]
MOV CL,AL
INC CL ;INCREMENT EXT #
CALL COMP_EXT ;DID WE CROSS A DIR FCB BOUNDARY ?
JZ OPENR3 ;NO
PUSH BX
PUSH CX
call close ;close current extent
;lret remains at enddir
;if we cannot open next ext
POP CX
POP BX
; call endofdir
; jz ret13 ;return if end
CMP LRET,0FFH
JNE $+3
RET
MOV AL,MAXEXT
AND AL,CL
MOV [BX],AL ;UPDATE FCB EXTENT FIELD
JNZ OPENR0 ;BRANCH IF IN SAME MODULE
; ;increment extent number
; mov bx,info
; add bx,extnum ;bx=.fcb(extnum)
; mov al,[bx]
; inc al
; and al,maxext
; mov [bx],al ;fcb(extnum)=++1
; jz openmod ;move to next module if 0
; ;may be in same extent group
; mov ch,al
; mov al,extmsk
; and al,ch
; ;if 0, then not in same group
; and al,fcbcopied ;true if fcb was copied to dir
; ;puts 0 in al if not written
; jz openr0 ;go to next physical extent
; ;result is non zero,
; ;so we must be in same extent
; jmps openr1 ;to copy fcb info
openmod:
;extent number overflow, go to next module
add bx,(modnum-extnum) ;bx=.fcb(modnum)
inc b[bx] ;fcb(modnum)=++1
;module number incremented,
;check for overflow
mov al,[bx]
and al,maxmod ;mask high order bits
jz openerr ;cannot overflow to 0
;otherwise, ok to continue
;with new module
openr0:
MOV XDCNT,0FFFFH ;RESET XDCNT FOR MAKE
if MPM
MOV BYTE PTR SDCNT+1,0FFH
endif
mov cl,namlen
call srch ;next extent found?
jnz openr1
;end of file encountered
mov al,rmf
inc al ;0ffh becomes 00 if read
jz openerr ;sets lret = 1
;try to extend current file
call make
;cannot be end of directory
; call endofdir
jz openerr ;with lret = 1
if MPM
CALL FIX_OLIST_ITEM
endif
MOV COMP_FCB_CKS,TRUE
jmps openr2
openr1:
MOV COMP_FCB_CKS,TRUE ;SET FCB CHECKSUM FLAG
;not end of file, open
call opencopy
openr2:
call getfcb ;set parameters
xor al,al
MOV VRECORD,AL
jmp staret ;lret = 0
; ret
openerr:
CALL GETMODNUM
MOV AL,SAVE_MOD
MOV [BX],AL
CALL GETEXTA
MOV AL,SAVE_EXT
MOV [BX],AL
CALL MAKE_FCB_INV
MOV COMP_FCB_CKS,0FFH
;cannot move to next extent
;of this file
call setlret1 ;lret = 1
jmp setfwf ;ensure that it will not
;be closed
;ret
OPENR3:
MOV [BX],CL ;INCREMENT EXTENT FIELD
CALL GET_DIR_EXT
MOV CL,AL
CALL RESTORE_RC
CALL SET_RC
JMPS OPENR2
;
;*************** end bdos file system part 2 ***************
end