mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-25 09:24:19 +00:00
1398 lines
31 KiB
Plaintext
1398 lines
31 KiB
Plaintext
|
||
;************ bdos file system part 2 ************
|
||
|
||
getallocbit:
|
||
;-----------
|
||
; given allocation vector position on cx, return byte
|
||
; containing cx shifted so that the least significant
|
||
; bit is in the low order accumulator position. bx is
|
||
; the address of the byte for possible replacement in
|
||
; memory upon return, and dh contains the number of shifts
|
||
; required to place the returned value back into position
|
||
; entry: CX = allocation vector bit index
|
||
; exit: AL = alloc bit index in low order bit
|
||
; BX = allocation vector byte offset
|
||
; CL = # of shifts required to restore bit in byte
|
||
|
||
mov bx,cx
|
||
and cl,111b
|
||
inc cl
|
||
mov ch,cl ;ch and cl both contain the
|
||
;number of bit positions to
|
||
;shift
|
||
mov cl,3 ;shift bit address right 3
|
||
shr bx,cl ; for byte address
|
||
;dx shr 3 to dx
|
||
add bx,alloca ;base addr. of alloc. vector
|
||
;byte to a, hl =
|
||
mov al,[bx] ;.alloc(cx shr 3)
|
||
;now move the bit to the
|
||
mov cl,ch ;low order position of al
|
||
rol al,cl
|
||
ret71: ret
|
||
|
||
setallocbit:
|
||
;-----------
|
||
; entry: CX = allocation vector bit index to set or reset
|
||
; DL = low order bit is value to set into vector
|
||
|
||
push dx
|
||
call getallocbit ;shifted val al,count in dl
|
||
and al,11111110b ;mask low bit to zero
|
||
;(may be set)
|
||
pop dx
|
||
or al,dl ;low bit of cl masked into al
|
||
|
||
rotr: ;rotate and replace byte into allocation vector
|
||
;----
|
||
; entry: AL = byte from allocation vector
|
||
; BX = allocation vector byte offset
|
||
; CL = # of rotates required to restore alloc vector byte
|
||
|
||
ror al,cl
|
||
mov [bx],al
|
||
ret
|
||
|
||
get_nalbs: ;get # of allocation vector bytes
|
||
;---------
|
||
; exit: BX = # of bytes in allocation vector
|
||
|
||
mov bx,maxall
|
||
mov cl,3 ;perform maxall/8
|
||
shr bx,cl
|
||
inc bx
|
||
ret
|
||
|
||
copy_alv: ;copy allocation vector
|
||
;--------
|
||
; entry: Z flag = 1 - copy 1st ALV to 2nd
|
||
; = 0 - copy 2nd ALV to 1st
|
||
|
||
pushf
|
||
call get_nalbs
|
||
mov si,alloca
|
||
mov di,si
|
||
add di,bx
|
||
mov cx,bx
|
||
popf! jz copya0
|
||
xchg si,di
|
||
copya0:
|
||
rep movsb
|
||
call ua_discard ;discard unallocated check blocks
|
||
ret8a: ret
|
||
|
||
scndma: ;set/reset 1st ALV
|
||
;------
|
||
; 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)
|
||
; entry: CL = 1/0 - set/reset blocks in alloc vector
|
||
|
||
call get_dptra ;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:
|
||
pop dx ;loop for each diskmap entry
|
||
dec cl ;recall bit parity
|
||
jnz scndma0a
|
||
or dl,dl! jnz ret8a ;all done scanning?
|
||
mov bx,alloca
|
||
mov ax,dirblk! or [bx],ax ;restore directory blocks
|
||
ret
|
||
scndma0a:
|
||
push dx ;no, get next entry for scan
|
||
cmp single,0 ;replace bit parity
|
||
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: ;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
|
||
scan3: ;bit set to 0/1
|
||
pop bx
|
||
inc bx ;to next bit position
|
||
pop cx ;recall counter
|
||
jmps scndm0 ;for another item
|
||
|
||
scndmab: ;set/reset 1st and 2nd ALV
|
||
;-------
|
||
push cx
|
||
call scndma
|
||
pop cx
|
||
;jmp scndmb
|
||
|
||
scndmb: ;set/reset 2nd ALV
|
||
;------
|
||
push cx
|
||
call get_nalbs
|
||
pop cx
|
||
mov ax,alloca! push ax
|
||
add ax,bx
|
||
mov alloca,ax
|
||
call scndma
|
||
pop alloca
|
||
ret
|
||
|
||
initialize:
|
||
;----------
|
||
; initialize the current disk
|
||
; lret = false ;set to true if $ file exists
|
||
; compute the length of the allocation vector - 2
|
||
|
||
if BMPM
|
||
mov dx,tlog
|
||
call test_vector ;is tlog(curdsk) on
|
||
jz initialize1 ;no
|
||
mov bx,offset tlog ;tlog(curdsk) = off
|
||
call remove_drive
|
||
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 set_end_dir
|
||
test_dir1:
|
||
mov cl,0feh
|
||
call read_dir
|
||
cmp flushed,false ;has a change in media occurred?
|
||
jne initialize1 ; yes - login drive
|
||
call end_of_dir
|
||
jnz test_dir1
|
||
ret ; no - do not relog in drive
|
||
initialize1: ;log in drive
|
||
|
||
endif
|
||
|
||
cmp chksiz,8000h ;if chksiz = 8000h
|
||
jne init1
|
||
mov bx,drvlbla ; and lsn <> 0 skip relog
|
||
mov al,1! xchg 2[bx],al
|
||
or al,al! jnz init23 ; only copy allocation vector
|
||
init1:
|
||
MOV BX,DAT_BCBA ;DISCARD ACTIVE DATA BCB'S
|
||
CALL DISCARD
|
||
CALL discard_dir ;DISCARD ACTIVE DIRECTORY BCB'S
|
||
|
||
call get_nalbs ;bx = # of allocation vector bytes
|
||
mov cx,bx
|
||
mov di,alloca ;base of allocation vector
|
||
mov ax,dirblk
|
||
stosw ;sets reserved directory blks
|
||
dec cx! dec cx
|
||
xor ax,ax ;fill the allocation vector
|
||
rep stosb ;with zeros
|
||
;allocation vector initialized
|
||
;set the reserved space for
|
||
mov bx,drvlbla ;the directory
|
||
mov [bx],al ;zero directory label data byte
|
||
mov byte ptr 1[bx],al ;ZERO DRIVE'S MEDIA FLAG
|
||
INC BYTE PTR 2[BX] ;INCREMENT DRIVE'S LOGIN SEQ #
|
||
|
||
MOV ARECORD1,ax ;hash table offset
|
||
|
||
mov bx,cdrmaxa ;cdrmax = 3 (scans at least
|
||
mov w[bx],3 ;one directory record)
|
||
;cdrmax = 0000
|
||
call setenddir ;dcnt = enddir
|
||
;read directory entries and
|
||
;check for allocated storage
|
||
init2:
|
||
mov cl,true
|
||
call read_dir
|
||
call endofdir
|
||
jnz $+5
|
||
init23:
|
||
jmp copy_alv ;copy allocation vector and return
|
||
;not end of directory,
|
||
;valid entry ?
|
||
|
||
call fix_hash ;COMPUTE HASH FOR DIRECTORY ITEM
|
||
call get_dptra ;bx = buffa + dptr
|
||
mov al,[bx]
|
||
CMP al,21H ;IS ENTRY SFCB?
|
||
JZ INIT2 ;YES
|
||
|
||
cmp al,empty
|
||
jz init2 ;go get another item
|
||
;not empty,user code the same?
|
||
|
||
cmp al,20h ;is entry directory label ?
|
||
je drv_lbl ;yes
|
||
test al,10h ;is entry special type of fcb ?
|
||
jnz initial3 ;yes
|
||
|
||
;now scan the disk map for
|
||
;allocated blocks
|
||
mov cl,1 ;set to allocated
|
||
call scndma
|
||
initial3:
|
||
call setcdr ;set cdrmax to dcnt
|
||
jmps init2 ;for another entry
|
||
drv_lbl:
|
||
mov al,extnum[bx]
|
||
mov bx,drvlbla
|
||
mov [bx],al
|
||
jmps initial3
|
||
|
||
|
||
cpydirloc:
|
||
;---------
|
||
; copy directory location to lret following
|
||
; delete, rename, ... ops
|
||
|
||
mov al,dirloc
|
||
jmp set_lret
|
||
;ret
|
||
|
||
chk_wild: ;check fcb for ? marks
|
||
;--------
|
||
; entry: BX = .fcb(0)
|
||
; exit: BX = preserved
|
||
; Z flag = 1 if ? mark found
|
||
|
||
mov cx,11
|
||
mov si,bx! inc si
|
||
chk_wild1:
|
||
lodsb
|
||
and al,07fh
|
||
cmp al,'?'
|
||
jz ret10 ;rtn with z flag set if ? fnd
|
||
loop chk_wild1
|
||
or al,al ;rtn with z flag reset - no ?s
|
||
ret10: ret
|
||
|
||
check_wild: ;check for ? in file name or type
|
||
;----------
|
||
mov bx,offset info_fcb
|
||
check_wild0: ;entry point used by rename
|
||
call chk_wild
|
||
jnz ret10
|
||
mov ah,9 ;extended error 9
|
||
jmp set_aret
|
||
|
||
|
||
SET_HASH: ; set hash length and fill in hash
|
||
;--------
|
||
; hash format: xxsuuuuu xxxxxxxx xxxxxxxx ssssssss
|
||
; x = hash code of fcb name field
|
||
; u = low 5 bits of user number
|
||
; s = shr(mod || ext,extshf)
|
||
; entry: CL = searchl
|
||
; BX = .info_fcb
|
||
; exit: hashl = 0,2 or 3
|
||
; hash(*) = hash code for length of hashl+1
|
||
|
||
CMP HASH_SEG,0 ;DOES HASH TBL EXIST ON DRIVE?
|
||
JE ret10 ;NO
|
||
OR cl,cl ;DOES SEARCHL = 0?
|
||
JZ ret10 ;YES
|
||
CMP cl,12 ;IS SEARCHL < 12?
|
||
jb SET_HASH2 ;YES
|
||
MOV AL,2
|
||
je SET_HASH1 ;SEARCHL = 12
|
||
MOV AL,3
|
||
SET_HASH1:
|
||
MOV HASHL,AL ;HASHL = 2 OR 3
|
||
MOV AL,fx_intrn
|
||
if BCPM
|
||
cmp al,fxi16 ;is func# = close?
|
||
je get_hash ; yes
|
||
endif
|
||
cmp al,fxi35 ;is func# = compute file size?
|
||
je set_hash15 ; yes
|
||
CMP AL,fxi20 ;is func# >= read seqn?
|
||
jae GET_HASH ; yes
|
||
SET_HASH15:
|
||
MOV HASHL,2 ;HASHL = 2 FOR SEARCH, SEARCHN,
|
||
;AND DELETE IF NOT WILD
|
||
;HASHL = 2 FOR OPENS
|
||
CALL CHK_WILD ;IS FCB WILD?
|
||
JNZ GET_HASH ;NO
|
||
SET_HASH2: ;HASHL = 0 IF SEARCHL = 1 OR
|
||
mov hashl,0 ;SEARCH OR DELETE IS WILD
|
||
|
||
GET_HASH: ; fill in hash
|
||
;--------
|
||
; entry: BX = .info_fcb or .dir_fcb
|
||
; exit: hash(*) = hash code for fcb
|
||
|
||
MOV SI,BX ;SI = .FCB(0)
|
||
lods al
|
||
MOV HASH,AL ;HASH(0) = USER #
|
||
XOR BX,BX ;DL,BH,BL = 3 BYTE NAME HASH
|
||
AND AL,20H ;IS FCB(0) = E5H,20H,21H?
|
||
jz get_hash0 ;no
|
||
or byte ptr hash,10h ;??11???? = hash code for E5h,20h,21h
|
||
ret
|
||
GET_HASH0:
|
||
mov dl,al
|
||
MOV CX,11 ;LOOP COUNT
|
||
GET_HASH1:
|
||
CMP CL,6 ;IS LOOP COUNT = 6?
|
||
je GET_HASH2 ;YES
|
||
CMP CL,4 ;IS LOOP COUNT = 4?
|
||
je GET_HASH2 ;YES
|
||
shl bx,1 ;HASH = shl(HASH,1)
|
||
rcl dl,1
|
||
TEST CL,1 ;IS LOOP COUNT EVEN?
|
||
JNZ GET_HASH2 ;NO
|
||
shl bx,1 ;HASH = shl(HASH,1)
|
||
rcl dl,1
|
||
GET_HASH2:
|
||
lods al ;I = I + 1
|
||
AND al,7FH ;HASH = HASH +
|
||
SUB al,20H ; (FCB(I) & 7FH) -20H
|
||
ROR al,1 ; SHIFTED RIGHT ONE IF EVEN
|
||
JNC GET_HASH3
|
||
ROL al,1
|
||
GET_HASH3:
|
||
XOR ah,ah
|
||
ADD BX,ax
|
||
ADC dl,0
|
||
LOOP GET_HASH1
|
||
|
||
MOV WORD PTR HASH+1,BX ;HASH(1,2) = BX
|
||
MOV BX,OFFSET HASH
|
||
AND dl,3
|
||
ror dl,1! ror dl,1
|
||
OR [BX],dl ;HASH(0) = HASH(0) | ROR((AL & 3),2)
|
||
LODS AL
|
||
AND AL,1FH ;AL = FCB(EXT) & 1FH
|
||
INC SI
|
||
MOV AH,[SI] ;AH = FCB(MOD) & 3FH
|
||
AND AH,3FH
|
||
MOV CL,3
|
||
shl AL,CL
|
||
shr AX,CL ;AX = MOD || EXT
|
||
MOV dl,EXTMSK
|
||
shl ax,1 ;setup to shr(ax,extshf)
|
||
GET_HASH5:
|
||
shr ax,1
|
||
shr dl,1
|
||
jc get_hash5 ;AX = SHR(AX,EXTSHF)
|
||
|
||
AND AH,1 ;AH = AH & 1
|
||
ROR AH,CL ;CL = 3
|
||
OR [BX],AH ;HASH(0) = HASH(0) | ROR(AH,3)
|
||
MOV 3[BX],AL ;HASH(3) = AL
|
||
RET8D: RET
|
||
|
||
|
||
SEARCH_HASH: ;search hash table for hash(*) of length hashl
|
||
;-----------
|
||
; exit: Z flag = 0 if not successful
|
||
|
||
CMP HASH_SEG,0 ;DOES HASH TBL EXIST ON DRIVE?
|
||
JE RET8D ;NO
|
||
MOV AL,searchL ;DOES SEARCHL = 0?
|
||
OR AL,AL
|
||
JZ RET8D ;YES
|
||
CMP HASHL,0FFH ;IS HIGHL = 0FFH?
|
||
JZ RET8D ;YES - SEARCH_HASH TEMPORARILY DISABLED
|
||
MOV BX,CDRMAXA
|
||
MOV cx,[BX]
|
||
DEC AL ;IF SEARCHL ~= 1
|
||
JNZ SEARCH_H0 ; THEN CX = CDRMAX
|
||
MOV cx,DIRMAX ; ELSE CX = DIRMAX
|
||
SEARCH_H0:
|
||
MOV bx,DCNT
|
||
SUB cx,bx ;CX = CX - DCNT = loop count
|
||
JZ RET8D
|
||
MOV ES,HASH_SEG
|
||
|
||
inc bx ;DCNT = DCNT + 1
|
||
MOV di,bx ;SAVE DCNT + 1
|
||
shl di,1! shl di,1 ;multiply by 4
|
||
sub di,4 ;setup for search_h2
|
||
;DI = .HASH(DCNT)
|
||
;BX = DCNT + 1
|
||
;CX = LOOP COUNT
|
||
CALL SEARCH_H2 ;Z FLAG SET IF FOUND
|
||
|
||
MOV AX,DS
|
||
MOV ES,AX
|
||
RET
|
||
|
||
SEARCH_H2:
|
||
ADD DI,4
|
||
MOV SI,OFFSET HASH
|
||
lods al ;DO USER #'S MATCH?
|
||
XOR AL,ES:[DI]
|
||
MOV dl,AL
|
||
AND AL,1FH
|
||
JNZ SEARCH_H4 ;NO
|
||
CALL SEARCH_H7 ;DO HASH CODES MATCH?
|
||
JZ SEARCH_H5 ;YES
|
||
SEARCH_H3:
|
||
INC BX ;DCNT = DCNT + 1
|
||
LOOP SEARCH_H2
|
||
|
||
; UNSUCCESSFUL HASH SEARCH
|
||
|
||
CMP DCNT,0FFFFH ;WAS SEARCH FROM BEGINNING OF DIR?
|
||
JNZ RET8E ;NO
|
||
mov ax,ds! mov es,ax ;restore ES for tst_log_fxs
|
||
CALL TST_LOG_FXS ;IS DRV REM & FX = 15,17,13,22,23,30?
|
||
JNZ RET8E ;NO
|
||
MOV HASHL,0FFH ;DISABLE HASH TABLE SEARCH
|
||
RET8E: RET
|
||
|
||
SEARCH_H4:
|
||
MOV AL,BYTE PTR XDCNT+1 ;DOES XDCNT+1 = 0FFH?
|
||
INC AL
|
||
jnz search_h41 ;no
|
||
cmp es:b[di],0f5h ;is hash empty entry
|
||
jne search_h3 ; no
|
||
jmps search_h42 ; yes - save dcnt in xdcnt
|
||
SEARCH_H41:
|
||
INC AL ;DOES XDCNT+1 = 0FEH?
|
||
JNZ SEARCH_H3 ;NO
|
||
CALL SEARCH_H7 ;DO HASH CODES MATCH?
|
||
JNZ SEARCH_H3 ;NO
|
||
mov al,find_xfcb
|
||
inc al ;does FIND_XFCB = 0FFh?
|
||
jnz search_h43 ; no
|
||
test es:b[di],10h ;is hash entry an xfcb
|
||
jz search_h3 ; no
|
||
test dl,0Fh ;does user field match?
|
||
jnz search_h3 ; no
|
||
SEARCH_H42:
|
||
mov xdcnt,bx ; yes - xdcnt = dcnt
|
||
jmps search_h3
|
||
SEARCH_H43:
|
||
inc al ;does find_xfcb = 0FEh?
|
||
jnz search_h45 ; no
|
||
test dl,0Fh ;does user field match?
|
||
jnz search_h3 ; no
|
||
jmps search_h5 ; yes - save dcnt
|
||
SEARCH_H45:
|
||
test es:b[di],01Fh ;IS HASH ENTRY FOR USER 0?
|
||
jnz SEARCH_H3 ;NO
|
||
SEARCH_H5: ;save dcnt
|
||
MOV DX,DCNT ;HASH TABLE MATCH
|
||
DEC BX
|
||
MOV DCNT,BX
|
||
MOV AL,BL
|
||
AND AL,3
|
||
CMP AL,3 ;DOES DCNT & 3 = 3?
|
||
JZ RET8F ;YES
|
||
AND BL,0FCH
|
||
AND DL,0FCH ;DOES PREVIOUS DCNT =
|
||
CMP BX,DX ;NEW DCNT?
|
||
JZ RET8F ; yes
|
||
or rd_dir_flag,0fh ; no - locate new directory record
|
||
XOR AL,AL ;SET ZERO FLAG
|
||
RET
|
||
|
||
SEARCH_H7:
|
||
MOV AL,HASHL ;ALL ENTRIES MATCH IF
|
||
OR AL,AL ;does HASHL = 0?
|
||
JZ RET8F ; yes
|
||
mov ah,0E0h ;if hashl = 3 then mask = 0F0h
|
||
cmp al,3! je search_h8 ;else mask = 0D0h
|
||
mov ah,0C0h ; - hashl = 2 - dont test s field
|
||
search_h8:
|
||
test dl,ah ;do mask bits match
|
||
JNZ RET8F ;no
|
||
XOR AH,AH
|
||
XCHG AX,CX ;CX = hash length
|
||
PUSH DI ;COMPARE HASH ENTRIES
|
||
INC DI
|
||
REPE CMPS AL,AL ;Z FLAG SET IF MATCH
|
||
XCHG AX,CX
|
||
POP DI
|
||
RET8F: RET
|
||
|
||
FIX_HASH:
|
||
;--------
|
||
CMP HASH_SEG,0
|
||
JZ RET8F
|
||
PUSH WORD PTR HASH ;SAVE CURRENT HASH
|
||
PUSH WORD PTR HASH+2
|
||
CALL GET_DPTRA
|
||
CALL GET_HASH ;COMPUTE HASH FROM DIR ENTRY
|
||
MOV AX,DCNT ;MOVE TO HASH_TABLE(DCNT)
|
||
shl ax,1! shl ax,1
|
||
MOV DI,AX
|
||
MOV ES,HASH_SEG
|
||
MOV SI,OFFSET HASH
|
||
mov cx,2
|
||
REP MOVS ax,ax
|
||
MOV AX,DS
|
||
MOV ES,AX
|
||
POP WORD PTR HASH+2 ;RESTORE CURRENT HASH
|
||
POP WORD PTR HASH
|
||
RET
|
||
|
||
if BMPM
|
||
|
||
swap: ;swap sdcnt with sdcnt0
|
||
;----
|
||
mov ax,sdcnt
|
||
xchg ax,sdcnt0
|
||
mov sdcnt,ax
|
||
ret
|
||
endif
|
||
|
||
save_dcnt_pos1:
|
||
;--------------
|
||
cmp byte ptr xdcnt+1,0ffh
|
||
jne ret8f
|
||
|
||
save_dcnt_pos:
|
||
;-------------
|
||
mov ax,dcnt
|
||
mov xdcnt,ax
|
||
ret
|
||
|
||
searchi: ;search initialization
|
||
;-------
|
||
mov bx,offset info_fcb
|
||
mov searcha,bx ;searcha = .info_fcb
|
||
|
||
searchi1:
|
||
mov dirloc,0ffh ;changed if actually found
|
||
mov searchl,cl ;searchl = cl
|
||
CALL SET_HASH
|
||
ret
|
||
|
||
search_1_name: ;search for first fcb matching name
|
||
;-------------
|
||
xor ax,ax
|
||
MOV info_fcb+extnum,al
|
||
MOV info_fcb+modnum,al
|
||
|
||
search_name: ;search matching name
|
||
;-----------
|
||
mov cl,namlen
|
||
jmps search
|
||
|
||
search_ext:
|
||
;----------
|
||
mov cl,extnum
|
||
|
||
search: ;search for directory element at .info_fcb
|
||
;------
|
||
; entry: CL = search length
|
||
|
||
call searchi
|
||
search1: ;entry point used by rename
|
||
call setenddir ;dcnt = enddir
|
||
;to start at the beginning
|
||
;(drop through to searchn)
|
||
;
|
||
searchn:
|
||
;-------
|
||
; search for the next directory element, assuming
|
||
; a previous call on search which sets searcha and searchhl
|
||
; exit: Z flag = 0 for successful searches
|
||
|
||
if BMPM
|
||
xor al,al
|
||
xchg user_zero_pass,al
|
||
test al,al
|
||
jz searchn1 ;if user_zero_pass then do;
|
||
; user_zero_pass = false;
|
||
call swap ; call swap:
|
||
; end;
|
||
searchn1:
|
||
|
||
endif
|
||
if BCPM
|
||
mov user_zero_pass,false
|
||
endif
|
||
|
||
CALL SEARCH_HASH
|
||
JNZ searchFIN
|
||
|
||
mov cl,false
|
||
call read_dir ;read next dir element
|
||
call endofdir
|
||
jz searchfin
|
||
;skip to end if so
|
||
;not end of directory,
|
||
;scan for match
|
||
mov dx,searcha ;dx=beginning of user fcb
|
||
mov si,dx
|
||
lods al ;first character
|
||
cmp al,empty ;keep scanning if empty
|
||
jz searchnext
|
||
;not empty, may be end of
|
||
;logical directory
|
||
push dx ;save search address
|
||
call compcdr ;past logical end?
|
||
pop dx ;recall address
|
||
jnb searchfin
|
||
;artificial stop
|
||
searchnext:
|
||
call get_dptra ;bx = buffa+dptr
|
||
mov cl,searchl ;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 searchloop ;no
|
||
mov si,dx
|
||
cmp al,[si] ;does user # match ?
|
||
jnz searchloop ;no
|
||
MOV AL,FIND_XFCB
|
||
OR AL,AL ;IS FIND_XFCB ~= 0
|
||
jz searchn ; no
|
||
MOV SAVE_XFCB,AL ;
|
||
jmps searchok
|
||
|
||
searchfin: ;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 set_lret ;searches
|
||
|
||
searchloop:
|
||
or cl,cl
|
||
jz endsearch
|
||
mov si,dx
|
||
lods al ;fcb character
|
||
and al,07fh
|
||
cmp al,'?'
|
||
jz searchok ;? matches all
|
||
;scan next character if not
|
||
;chksum byte
|
||
cmp ch,chksum
|
||
jz searchok
|
||
;not the ubytes field,
|
||
;extent field
|
||
cmp ch,extnum ;may be extent field
|
||
jz chk_ext ;skip to search extent
|
||
|
||
cmp ch,modnum ;is field module # ?
|
||
jnz not_modnum ;no
|
||
and al,3fh ;yes - mask off high order bits
|
||
not_modnum:
|
||
sub al,[bx]
|
||
and al,7fh ;mask-out flags/extent modulus
|
||
jnz searchnm
|
||
jmps searchok ;matched character
|
||
|
||
chk_ext: ;AL = fcb character
|
||
;attempt an extent # match
|
||
if BMPM
|
||
cmp byte ptr sdcnt+1,true ;if sdcnt+1 = ff then do;
|
||
jne dont_save ; sdcnt = dcnt
|
||
mov si,dcnt
|
||
mov sdcnt,si ; end;
|
||
dont_save:
|
||
|
||
endif
|
||
|
||
push cx ;save counters
|
||
mov cl,[bx] ;directory character to c
|
||
call compext ;compare user/dir char
|
||
pop cx ;recall counters
|
||
jnz searchn_jmp ;skip if no match
|
||
test user_zero_pass,true
|
||
jz not_user0 ;if user0_pass and
|
||
inc bx! inc bx
|
||
cmp b[bx],0 ; matching extent & modnum = 0
|
||
jne searchn_jmp
|
||
call save_dcnt_pos ;save directory position
|
||
jmp searchn ; of matching fcb
|
||
not_user0:
|
||
|
||
;disable search under user zero if any fcb is found under
|
||
;the current user number
|
||
|
||
mov search_user0,false
|
||
searchok: ;current character matches
|
||
inc dx! inc bx
|
||
inc ch! dec cl
|
||
jmps searchloop
|
||
|
||
endsearch: ;entire name matches, return dir position
|
||
CMP SAVE_XFCB,0FFH ;is save_xfcb true
|
||
JNZ ENDSEARCH1 ;NO - 0 0R 0FEH
|
||
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:
|
||
xor al,al
|
||
mov dirloc,al
|
||
mov lret,al
|
||
mov ch,al
|
||
inc ch ;zero flag reset on successful
|
||
ret9: ret ;searches
|
||
|
||
searchnm: ;search no match routine
|
||
or ch,[bx] ;is fcb(0) and 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 BMPM
|
||
call swap
|
||
endif
|
||
|
||
jmps searchok
|
||
|
||
init_xfcb_search:
|
||
;----------------
|
||
mov al,0ffh ;find_xfcb = ffh
|
||
|
||
init_xfcb_search1:
|
||
;-----------------
|
||
; entry: AL = value to set find_xfcb
|
||
|
||
mov find_xfcb,al
|
||
mov al,0feh
|
||
mov byte ptr xdcnt+1,al ;xdcnt+1 = feh
|
||
RET9A: ret
|
||
|
||
does_xfcb_exist:
|
||
;---------------
|
||
cmp byte ptr xdcnt+1,0feh ;if xdcnt+1 = feh then return
|
||
je ret9
|
||
call set_dcnt ;dcnt = xdcnt - 1
|
||
xor al,al
|
||
call init_xfcb_search1
|
||
mov bx,searcha ;of 10h into fcb(0)
|
||
or b[bx],10h
|
||
mov cl,extnum
|
||
call searchi1 ;search for xfcb
|
||
jmp searchn ;z flag set if unsuccessful
|
||
|
||
XDCNT_EQ_DCNT: ;SAVE FCB'S DCNT IN XDCNT
|
||
;-------------
|
||
MOV AX,DCNT
|
||
MOV XDCNT,AX
|
||
RET
|
||
|
||
RESTORE_DIR_FCB: ;REPOSITION SEARCH TO FCB
|
||
;---------------
|
||
CALL SET_DCNT ;WHOSE DCNT IS SAVED IN XDCNT
|
||
MOV CL,NAMLEN
|
||
CALL SEARCHI
|
||
JMP SEARCHN
|
||
|
||
delet: ;delete the currently addressed file
|
||
;-----
|
||
CALL GET_ATTS ;F5' = DELETE XFCB'S ONLY
|
||
deletex:
|
||
MOV AL,0FEH ; RETAIN FILE'S LOCK
|
||
CALL INIT_XFCB_SEARCH1 ;HAVE SEARCH RETURN FCB'S & XFCB'S
|
||
|
||
; DELETE PASS 1 - CHECK R/O ATTRIBUTES AND XFCB PASSWORDS
|
||
|
||
CALL search_ext
|
||
JZ RET9A
|
||
DELETE00:
|
||
CALL GET_DPTRA
|
||
MOV AL,[BX]
|
||
AND AL,10H ;IS DIR FCB AN XFCB?
|
||
JNZ DELETE01 ;YES
|
||
|
||
if BMPM
|
||
CALL TST_OLIST
|
||
endif
|
||
|
||
TEST ATTRIBUTES,80H ;DELETE XFCB'S ONLY?
|
||
JNZ $+5 ;NO
|
||
CALL CKRODIR ;CHECK FILE R/O ATTRIBUTE
|
||
CALL GET_DIR_MODE ;HAVE PASSWORDS BEEN ENABLED BY
|
||
ROL AL,1 ;DIRECTORY LABEL?
|
||
JC DELETE02 ;YES
|
||
MOV BX,offset info_fcb
|
||
CALL CHK_WILD ;IS THIS A WILD CARD DELETE?
|
||
JZ DELETE02 ;YES
|
||
JMPS DELETE11 ;NO NEED FOR TWO PASSES
|
||
DELETE01:
|
||
CALL GET_DIR_MODE ;HAVE PASSWORDS BEEN ENABLED BY
|
||
ROL AL,1 ;DIRECTORY LABEL?
|
||
JNC delete02 ;NO
|
||
CALL CHK_XFCB_PASSWORD ;CHECK XFCB PASSWORD
|
||
jz delete02
|
||
call chk_pw_error
|
||
jmps deletex
|
||
DELETE02:
|
||
CALL SEARCHN
|
||
jnz DELETE00
|
||
|
||
; DELETE PASS 2 - DELETE ALL MATCHING FCB'S AND/OR XFCB'S
|
||
|
||
CALL search_ext
|
||
DELETE10:
|
||
JNZ DELETE11
|
||
JMP CPYDIRLOC ;DELETE FINISHED
|
||
DELETE11:
|
||
CALL GET_DPTRA
|
||
MOV AL,[BX]
|
||
AND AL,10H ;IS DIR FCB AN XFCB?
|
||
JNZ DELETE12 ;YES
|
||
|
||
if BMPM
|
||
PUSH BX
|
||
CALL CHK_OLIST
|
||
POP BX
|
||
endif
|
||
|
||
TEST ATTRIBUTES,80H ;XFCB ONLY DELETE?
|
||
JNZ DELETE13 ;YES
|
||
|
||
DELETE12:
|
||
MOV B[BX],0E5H ;DELETE DIR XFCB
|
||
delete13:
|
||
pushf
|
||
call get_dtba8
|
||
or al,al! jnz delete14
|
||
mov [bx],al
|
||
delete14:
|
||
CALL WRDIR ;UPDATE DIRECTORY RECORD
|
||
popf
|
||
JNZ delete15
|
||
MOV CL,0
|
||
CALL scndmab ;RETURN BLOCKS IF FCB
|
||
delete15:
|
||
CALL FIX_HASH ;UPDATE DIRECTORY HASH TABLE
|
||
CALL SEARCHN
|
||
jmps DELETE10
|
||
|
||
getblock:
|
||
;--------
|
||
; given allocation vector position cx, find the zero bit
|
||
; closest to this position by searching right 1st then left.
|
||
; 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
|
||
; entry: CX = starting block number to search from
|
||
; exit: BX = available block number, 0000 if not found
|
||
|
||
mov dx,cx ;copy start pos. to dx
|
||
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
|
||
;bit is one, so try the right
|
||
pop dx! pop cx ;left, right restored
|
||
lefttst:
|
||
or cx,cx
|
||
jz righttst ;skip if left=0000
|
||
;left not at position zero,
|
||
dec cx ;bit zero ?
|
||
push dx! push cx ;left,right pushed
|
||
call getallocbit
|
||
rcr al,1
|
||
jae rblok ;return block number if zero
|
||
pop cx! pop dx ;restore left and right ptr
|
||
jmps righttst ;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:
|
||
or cx,cx
|
||
jnz lefttst
|
||
mov bx,cx ;cannot find an available
|
||
ret ;bit, return 0000
|
||
|
||
copy_dir2:
|
||
;---------
|
||
push dx ;save length for later
|
||
mov ch,0 ;double index to cx
|
||
mov dx,offset info_fcb ;bx = source for data
|
||
add dx,cx ;dx=.fcb(cl), source for copy
|
||
call get_dptra ;bx=.buff(dptr), destination
|
||
pop cx ;dx=source, bx=dest, c=length
|
||
ret
|
||
|
||
copy_dir:
|
||
;--------
|
||
; copy fcb information starting
|
||
; into the currently addressed directory entry
|
||
|
||
mov dh,80h ;dh = attribute mask
|
||
copy_dir0:
|
||
;---------
|
||
; entry: DL = # of characters to copy
|
||
; DH = attribute mask
|
||
|
||
call copy_dir2 ;init regs bx, cx, dx for copy
|
||
inc cl
|
||
copy_dir1:
|
||
dec cl
|
||
JNZ $+5
|
||
JMP wrdir ;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_user_no:
|
||
;------------
|
||
mov al,info_fcb ;fcb(16) = fcb(0)
|
||
mov bx,offset info_fcb+dskmap
|
||
mov [bx],al ;bx = .fcb(16)
|
||
ret
|
||
|
||
open: ;search for the directory entry, copy to fcb
|
||
;----
|
||
call search_name
|
||
open1:
|
||
jz ret11 ;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 get_dptra
|
||
mov dx,bx ;dx = .buff(dptr)
|
||
mov bx,offset info_fcb ;bx=.fcb(0)
|
||
mov cl,nxtrec ;length of move operation
|
||
call move ;from .buff(dptr) to .fcb(0)
|
||
;note that entire fcb is
|
||
;copied, including indicators
|
||
call get_dir_ext
|
||
mov cl,al ;cl = dir_ext
|
||
pop ax! pop bx
|
||
mov [bx],al ;restore modnum
|
||
dec bx! dec bx
|
||
mov [bx],ah ;restore extnum number
|
||
|
||
; bx = .user extent#, 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
|
||
|
||
set_rc:
|
||
;------
|
||
; entry: BX = .user extent #
|
||
; CL = dir extent #
|
||
|
||
xor ch,ch
|
||
mov si,offset info_fcb+reccnt
|
||
mov al,[bx] ;al = current extent
|
||
sub al,cl ;compare fcb ext to dir ext
|
||
jz set_rc2 ;fcb ext = dir ext
|
||
; actual_rc = 0, fcb(rc) = fcb(rc)
|
||
mov al,ch
|
||
jae set_rc1 ;fcb ext > dir ext
|
||
; actual_rc = 0, fcb(rc) = 0
|
||
|
||
mov al,128 ;fcb ext < dir ext
|
||
or al,[si] ; fcb(rc) = 128 | fcb(rc)
|
||
set_rc1:
|
||
mov [si],al
|
||
ret11: ret
|
||
|
||
set_rc2:
|
||
cmp b[si],al ;is fcb(rc) = 0?
|
||
jnz ret11 ;no
|
||
set_rc3:
|
||
xor al,al ;AL = 0
|
||
mov b[si],al ;required by func 99
|
||
cmp dminx,al ;do blocks exist in fcb?
|
||
jz ret11 ;no
|
||
mov b[si],80h ;fcb(rc) = 80h
|
||
ret
|
||
|
||
restore_rc:
|
||
;----------
|
||
; if actual_rc ~= 0 then fcb(rc) = actual_rc
|
||
; entry: BX = .fcb(extnum)
|
||
|
||
mov al,info_fcb+reccnt
|
||
cmp al,81h
|
||
jb restore_rc1
|
||
and al,7fh
|
||
mov info_fcb+reccnt,al
|
||
restore_rc1:
|
||
ret
|
||
|
||
mergezero:
|
||
;---------
|
||
; if fcb1(i) = 0 then fcb1(i) := fcb2(i)
|
||
; entry: BX = .fcb1(i)
|
||
; DX = .fcb2(i)
|
||
|
||
cmp w[bx],0
|
||
jnz ret12 ;rnz
|
||
mov si,dx
|
||
lods ax
|
||
mov [bx],ax
|
||
ret12: ret
|
||
|
||
close_fcb:
|
||
;---------
|
||
test byte ptr chksiz+1,080h ;is drive permanent
|
||
jnz close_fcb1 ; yes
|
||
mov rd_dir_flag,0f0h ; no - must read directory to
|
||
close_fcb1: ; verify media has not changed
|
||
call search_name ;locate file
|
||
jz ret12 ;return if not found
|
||
;merge the disk map at info_fcb
|
||
call get_dptra
|
||
add bx,dskmap
|
||
mov dx,bx ;DX = .buff(dptr+16)
|
||
mov bx,offset info_fcb+dskmap ;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]
|
||
jz dmset ;fcb(i) = buff(i)?
|
||
jmps mergerr ;if not 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 bx,dx
|
||
sub bx,(fcblen-extnum)
|
||
push bx
|
||
call get_dir_ext
|
||
pop si ;SI = .fcb(extnum),
|
||
;BX = .buff(dptr+extnum)
|
||
mov cl,[si] ;CL = fcb extent number
|
||
mov ch,[bx] ;CH = buff extent number
|
||
|
||
mov [si],al ;fcb(ext) = dir(ext)
|
||
mov [bx],al ;buff(dptr+ext) = dir(ext)
|
||
add si,(reccnt-extnum) ;SI = fcb(rc)
|
||
add bx,(reccnt-extnum) ;BX = buff(rc)
|
||
|
||
cmp al,cl! jne mrg_rc1 ;fcb(ext)~=dir(ext)=buff(ext)
|
||
cmp al,ch! jne mrg_rc2 ;fcb(ext)=dir(ext)~=buff(ext)
|
||
|
||
mov al,[si] ;fcb(ext)=dir(ext)=buff(ext)
|
||
|
||
; under MP/M reccnt may have been extended
|
||
; by another process if the file was opened in
|
||
; unlocked mode - since extents match, set
|
||
; both reccnt fields to the higher value
|
||
|
||
cmp al,[bx]! jb mrg_rc1
|
||
or al,al! jne mrg_rc2
|
||
call set_rc3
|
||
mrg_rc1:
|
||
xchg bx,si ;fcb(rc) = buff(rc)
|
||
mrg_rc2:
|
||
mov al,[si]! mov [bx],al ;buff(rc) = fcb(rc)
|
||
|
||
if BMPM
|
||
test dont_close,true
|
||
jz $+3
|
||
ret
|
||
endif
|
||
|
||
call get_dptra ;set t3' off indicating file update
|
||
add bx,11
|
||
mov al,[bx]
|
||
and al,7fh
|
||
mov [bx],al
|
||
call setfwf
|
||
mov cl,1
|
||
call scndmb ;set 2nd ALV
|
||
jmp wrdir ;ok to "wrdir" here -
|
||
;1.4 compatible
|
||
; ret
|
||
mergerr:
|
||
call setfwf ;elements did not merge ok
|
||
mov word ptr 2[bx],0ffffh ;flag fcb as invalid
|
||
jmp lret_eq_ff ;=255 non zero flag set
|
||
|
||
close: ;locate the directory element and re-write it
|
||
;-----
|
||
xor ax,ax
|
||
mov lret,al
|
||
|
||
if BMPM
|
||
mov dont_close,al
|
||
endif
|
||
|
||
call nowrite
|
||
jnz ret13 ;skip close if r/o disk
|
||
;check file write flag -
|
||
;0 indicates written
|
||
mov al,info_fcb+modnum ;fcb(modnum) in AL
|
||
and al,fwfmsk
|
||
jnz ret13 ;return if bit remains set
|
||
close1:
|
||
call chk_inv_fcb
|
||
jz mergerr
|
||
|
||
if BMPM
|
||
mov comp_fcb_cks,true
|
||
endif
|
||
|
||
call get_dir_ext ;al = dir extent
|
||
mov cl,al
|
||
mov ch,[bx] ;ch = fcb(ext)
|
||
push cx ;save fcb(ext) & dir extent
|
||
mov [bx],al
|
||
call restore_rc
|
||
cmp cl,ch
|
||
jae $+5
|
||
call set_rc
|
||
call close_fcb
|
||
mov bx,offset info_fcb+extnum
|
||
pop cx
|
||
mov cl,[bx]
|
||
mov [bx],ch ;reset extent
|
||
jmp set_rc ;reset record count
|
||
|
||
make:
|
||
;----
|
||
; create a new file by creating a directory entry
|
||
; then opening the file
|
||
|
||
cmp xdcnt,0ffffh
|
||
je $+5
|
||
call set_dcnt
|
||
push word ptr info_fcb
|
||
mov info_fcb,empty ;info_fcb = empty
|
||
mov cl,1
|
||
|
||
call searchi
|
||
call searchn
|
||
;zero flag set if no space
|
||
pop word ptr info_fcb ;restore info_fcb
|
||
jnz $+3 ;return with error condition
|
||
ret13: ret ;255 if not found
|
||
|
||
test make_xfcb,0ffh ;return early if making an xfcb
|
||
jnz ret13
|
||
|
||
mov bx,offset info_fcb+chksum
|
||
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 cx,fcblen-namlen ;number of bytes to fill
|
||
mov al,1 ;clear al for fill
|
||
make0:
|
||
mov b[bx],0
|
||
inc bx
|
||
loop make0
|
||
dec al! jnz make1
|
||
call get_dtba
|
||
or al,al
|
||
mov cx,10
|
||
jz make0
|
||
make1:
|
||
call setcdr ;may have extended dir
|
||
;now copy entry to dir
|
||
mov cl,0
|
||
mov dx,fcblen ;dh = 0
|
||
call copy_dir0
|
||
|
||
pop bx! pop ax ;restore file write flag
|
||
mov [bx],al
|
||
|
||
mov actual_rc,0 ;actual_rc = 0
|
||
|
||
CALL FIX_HASH
|
||
|
||
;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.
|
||
; lret is set to 0 if successful
|
||
|
||
mov al,info_fcb+modnum
|
||
mov save_mod,al ;save current module #
|
||
mov bx,offset info_fcb+extnum
|
||
mov al,[bx]
|
||
mov cl,al
|
||
inc cl ;increment ext #
|
||
call compext ;did we cross a dir fcb boundary ?
|
||
jnz $+5
|
||
jmp openr3 ;no
|
||
push bx! push cx
|
||
call close ;close current extent
|
||
;lret remains at enddir
|
||
pop cx! pop bx ;if we cannot open next ext
|
||
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
|
||
|
||
; 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 BMPM
|
||
mov byte ptr sdcnt+1,0ffh
|
||
endif
|
||
|
||
call search_name ;next extent found?
|
||
jnz openr1
|
||
mov al,rmf ;end of file encountered
|
||
inc al ;0ffh becomes 00 if read
|
||
jz openerr ;sets lret = 1
|
||
call make ;try to extend current file
|
||
;cannot be end of directory
|
||
jz openerr ;with lret = 1
|
||
|
||
if BMPM
|
||
call fix_olist_item
|
||
mov comp_fcb_cks,true
|
||
endif
|
||
|
||
jmps openr2
|
||
openr1:
|
||
|
||
if BMPM
|
||
mov comp_fcb_cks,true ;set fcb checksum flag
|
||
endif ;not end of file, open
|
||
|
||
call opencopy
|
||
|
||
if BCPM
|
||
call set_lsn
|
||
endif
|
||
|
||
openr2:
|
||
call getfcb ;set parameters
|
||
xor al,al
|
||
mov vrecord,al
|
||
jmp set_lret ;lret = 0
|
||
;ret
|
||
|
||
openerr:
|
||
;-------
|
||
mov bx,offset info_fcb+extnum
|
||
mov al,save_mod
|
||
mov 2[bx],al
|
||
mov al,[bx]
|
||
dec al
|
||
and al,1fh
|
||
mov [bx],al
|
||
mov comp_fcb_cks,0ffh
|
||
;cannot move to next extent
|
||
;of this file
|
||
jmp set_lret1 ;lret = 1
|
||
;ret
|
||
openr3:
|
||
mov [bx],cl ;increment extent field
|
||
call get_dir_ext
|
||
mov cl,al
|
||
test high_ext,80h ;is open mode unlocked?
|
||
jnz openr4 ;yes
|
||
cmp al,[bx] ;is dir ext < fcb(ext)?
|
||
jae openr4 ;no
|
||
dec b[bx] ;decrement extent
|
||
cmp rmf,0ffh ;is this a read operation?
|
||
jne $+5 ;no
|
||
jmp set_lret1 ;yes - reading unwritten data
|
||
inc b[bx] ;restore extent
|
||
openr4:
|
||
call restore_rc
|
||
call set_rc
|
||
jmps openr2
|
||
|
||
;********** end bdos file system part 2 **********
|
||
|