mirror of
https://github.com/ksherlock/minix.fst.git
synced 2024-12-27 06:29:15 +00:00
996 lines
12 KiB
Plaintext
996 lines
12 KiB
Plaintext
;
|
|
; This file contains the implementation of get_dir_entry.
|
|
; It also contains other functions for finding an entry within
|
|
; a directory.
|
|
;
|
|
|
|
string asis
|
|
|
|
include 'gsos.equ'
|
|
include 'minix.equ'
|
|
include 'records.equ'
|
|
|
|
include 'fst.equ'
|
|
|
|
include 'fst.macros'
|
|
|
|
include 'M16.Debug'
|
|
|
|
include 'p.equ'
|
|
|
|
|
|
|
|
import disk_inode:v1_inode
|
|
import disk_super:v1_super
|
|
|
|
;
|
|
; dirent_entry 0 is a special case.
|
|
; (assuming base = 1, displacement = 1)
|
|
; first call:
|
|
; before
|
|
; dirent_entry = 0, dirent_zone = 0, dirent_offset = 0
|
|
; after:
|
|
; dirent_entry = 1, dirent_zone = 0, dirent_offset = 0
|
|
;
|
|
; subsequent calls:
|
|
; before
|
|
; dirent_entry = 1, dirent_zone = ..., dirent_offset = ...
|
|
; after
|
|
; dirent_entry = 2, dirent_zone = ..., dirent_offset = ...
|
|
;
|
|
|
|
; don't think this needs to be dp... move to a normal record.
|
|
|
|
|
|
data record
|
|
|
|
|
|
; size of the directory, divided by dirent_size.
|
|
size ds.l 1
|
|
|
|
displacement ds.w 1
|
|
|
|
dirent_size ds.w 1
|
|
dirent_zone ds.w 1
|
|
dirent_offset ds.w 1
|
|
dirent_entry ds.w 1
|
|
|
|
dirent ds v1L_dirent
|
|
|
|
endr
|
|
|
|
|
|
import init_fcr
|
|
import init_vcr
|
|
import load_inode
|
|
import read_data_block
|
|
|
|
import do_ignore
|
|
import do_eof
|
|
import do_blocks
|
|
import do_r_eof
|
|
import do_r_blocks
|
|
import do_access
|
|
import do_file_sys_id
|
|
import do_option_list
|
|
import do_create_date_time
|
|
import do_mod_date_time
|
|
import do_file_type
|
|
import do_aux_type
|
|
|
|
entry init
|
|
entry base_displace
|
|
entry find_next_dirent
|
|
entry find_absolute_dirent
|
|
entry find_dirent_block
|
|
entry count_entries
|
|
entry count_dirent_block
|
|
|
|
entry do_flags
|
|
entry do_name_buffer_0
|
|
entry do_name_buffer_1
|
|
entry do_entry_num
|
|
|
|
entry sparse_dirent_block
|
|
|
|
get_dir_entry procname export
|
|
|
|
with fst_parms
|
|
with dp
|
|
with data
|
|
|
|
;~DebugSetTrace #1
|
|
|
|
jsr init_vcr
|
|
jsr init_fcr
|
|
|
|
;brk $ea
|
|
|
|
; check for read-access
|
|
ldy #fcr.access
|
|
lda [<my_fcr],y
|
|
|
|
and #read_access
|
|
bne access_ok
|
|
|
|
lda #invalid_access
|
|
sec
|
|
rtl
|
|
|
|
access_ok
|
|
; is it a dir?
|
|
ldy #fcr.disk_inode.mode
|
|
lda [my_fcr],y
|
|
and #S_IFMT
|
|
cmp #S_IFDIR
|
|
beq dir
|
|
|
|
lda #bad_store_type
|
|
sec
|
|
rtl
|
|
|
|
dir
|
|
|
|
jsr init
|
|
jsr base_displace
|
|
bcc @ok
|
|
rtl
|
|
|
|
@ok
|
|
|
|
; if data.dirent.inode is valid, load the inode
|
|
; (if not valid, this was a base/displace of 0 to return
|
|
; the dirent count. field info will be returned from the
|
|
; directory inode)
|
|
|
|
|
|
lda data.dirent.inode
|
|
beq dispatch
|
|
|
|
; if inode == the directory inode (.) , no need to re-load it.
|
|
cmp inode
|
|
beq dispatch
|
|
|
|
sta inode
|
|
jsr load_inode
|
|
bcc dispatch
|
|
exit
|
|
rtl
|
|
|
|
dispatch
|
|
|
|
lda <call_class
|
|
beq class0
|
|
|
|
class1
|
|
lda [param_blk_ptr] ; pcount
|
|
dec a
|
|
asl a ; x 2
|
|
asl a ; x 4
|
|
tax
|
|
dispatch get_dir_entry_dcb_1
|
|
|
|
|
|
;~DebugHexDump param_blk_ptr, #DirEntryRecGS.__sizeof
|
|
|
|
lda tool_error
|
|
cmp #1
|
|
rtl
|
|
|
|
class0
|
|
ldx #get_dir_entry_dcb_0_size-4
|
|
dispatch get_dir_entry_dcb_0
|
|
lda tool_error
|
|
cmp #1
|
|
rtl
|
|
|
|
|
|
get_dir_entry_dcb_0
|
|
dc.w $00, do_ignore ; refnum
|
|
dc.w $02, do_flags
|
|
dc.w $04, do_ignore ; base
|
|
dc.w $06, do_ignore ; displacement
|
|
dc.w $08, do_name_buffer_0 ;
|
|
dc.w $0c, do_entry_num
|
|
dc.w $0e, do_file_type
|
|
dc.w $10, do_eof
|
|
dc.w $14, do_blocks
|
|
dc.w $18, do_create_date_time
|
|
dc.w $20, do_mod_date_time
|
|
dc.w $28, do_access
|
|
dc.w $2a, do_aux_type
|
|
dc.w $2e, do_file_sys_id
|
|
|
|
get_dir_entry_dcb_0_size equ *-get_dir_entry_dcb_0
|
|
|
|
get_dir_entry_dcb_1
|
|
;dc.w $00, do_ignore ; pCount
|
|
dc.w $02, do_ignore ; refnum
|
|
dc.w $04, do_flags
|
|
dc.w $06, do_ignore ; base
|
|
dc.w $08, do_ignore ; displacement
|
|
dc.w $0a, do_name_buffer_1 ;
|
|
dc.w $0e, do_entry_num
|
|
dc.w $10, do_file_type
|
|
dc.w $12, do_eof
|
|
dc.w $16, do_blocks
|
|
dc.w $1a, do_create_date_time
|
|
dc.w $22, do_mod_date_time
|
|
dc.w $2a, do_access
|
|
dc.w $2c, do_aux_type
|
|
dc.w $30, do_file_sys_id
|
|
dc.w $32, do_option_list
|
|
dc.w $36, do_r_eof
|
|
dc.w $3a, do_r_blocks
|
|
|
|
|
|
|
|
endp
|
|
|
|
|
|
init procname
|
|
|
|
with fst_parms,dp,data
|
|
|
|
; must be set up before hand.
|
|
;lda device
|
|
;sta dev_parms.dev_num
|
|
|
|
; directory entry (and inode lookup) should be cached.
|
|
lda #in_cache
|
|
sta dev_parms.dev_cache_pr
|
|
|
|
; should probably read half-blocks...
|
|
lda #1024
|
|
;sta dev_parms.dev_blk_size
|
|
sta dev_parms.dev_req_cnt
|
|
|
|
|
|
;stz dirent_offset
|
|
;stz dirent_entry
|
|
;stz dirent_zone
|
|
|
|
|
|
ldy #fcr.dirent_zone
|
|
lda [my_fcr],y
|
|
sta dirent_zone
|
|
|
|
ldy #fcr.dirent_offset
|
|
lda [my_fcr],y
|
|
sta dirent_offset
|
|
|
|
ldy #fcr.dirent_entry
|
|
lda [my_fcr],y
|
|
sta dirent_entry
|
|
|
|
|
|
stz data.dirent.inode
|
|
stz data.dirent.name
|
|
|
|
lda #v1_dirent.__sizeof
|
|
sta dirent_size
|
|
|
|
|
|
lda disk_inode.size
|
|
sta size
|
|
lda disk_inode.size+2
|
|
sta size+2
|
|
|
|
; / 2
|
|
lsr size+2
|
|
ror size
|
|
|
|
; / 4
|
|
lsr size+2
|
|
ror size
|
|
|
|
; / 8
|
|
lsr size+2
|
|
ror size
|
|
|
|
; / 16
|
|
lsr size+2
|
|
ror size
|
|
|
|
|
|
;~DebugHexDump <my_vcr, #vcr.__sizeof
|
|
|
|
ldy #vcr.super.magic
|
|
lda [my_vcr],y
|
|
|
|
cmp #v1L.MAGIC
|
|
bne minix
|
|
; this is
|
|
linux
|
|
; linux dirents are twice as big.
|
|
|
|
asl dirent_size
|
|
|
|
; / 32
|
|
lsr size+2
|
|
ror size
|
|
|
|
|
|
minix
|
|
rts
|
|
|
|
endp
|
|
|
|
|
|
base_displace procname
|
|
|
|
with fst_parms, dp
|
|
with data
|
|
|
|
; offset is $04 for class 0, $06 for class 1
|
|
lda #$04
|
|
clc
|
|
adc <call_class
|
|
tay
|
|
|
|
lda [param_blk_ptr],y ; base
|
|
cmp #3
|
|
bcs perr
|
|
|
|
asl a
|
|
tax
|
|
|
|
iny
|
|
iny
|
|
lda [param_blk_ptr],y ; displacement
|
|
sta displacement
|
|
|
|
jmp (base_table,x)
|
|
|
|
|
|
perr
|
|
lda #parm_range_err
|
|
sec
|
|
rts
|
|
|
|
base_table
|
|
dc.w absolute, forward, backward
|
|
|
|
absolute
|
|
; absolute with a displacement of 0 -> return total count.
|
|
;
|
|
cmp #0
|
|
beq @count
|
|
jmp find_absolute_dirent
|
|
@count
|
|
jmp count_entries
|
|
|
|
forward
|
|
jmp find_next_dirent
|
|
;
|
|
backward
|
|
; backward 0 ? == forward 0
|
|
cmp #0
|
|
beq forward
|
|
|
|
eor #$ffff
|
|
sec ; inc / clc
|
|
adc dirent_entry
|
|
sta displacement
|
|
|
|
jmp find_absolute_dirent
|
|
|
|
endp
|
|
|
|
|
|
|
|
count_entries procname
|
|
; count the number of entries.
|
|
|
|
with fst_parms
|
|
with dp, data
|
|
|
|
; read each block and count the entries.
|
|
; only handles direct blocks. so there.
|
|
|
|
|
|
; disk inode has been copied to the dp.
|
|
stz dirent_entry
|
|
ldx #0
|
|
zone_loop
|
|
stx dirent_zone
|
|
lda disk_inode.zone,x
|
|
bne @ok ; directory should not be sparse!
|
|
; sparse!
|
|
jsr sparse_dirent_block
|
|
bcs done
|
|
bra next
|
|
|
|
@ok
|
|
jsr read_data_block
|
|
bcs exit
|
|
|
|
; ~DebugHexDump <io_buffer, #1024
|
|
|
|
jsr count_dirent_block
|
|
lda size
|
|
beq done
|
|
|
|
next
|
|
ldx dirent_zone
|
|
inx
|
|
inx
|
|
cpx #v1.NR_DZONES*2
|
|
bcs done
|
|
bra zone_loop
|
|
;
|
|
; minix has 16-byte dirents.
|
|
; linux has 32-byte dirents.
|
|
|
|
|
|
done
|
|
|
|
; also reset the displacement to 0.
|
|
lda #0
|
|
ldy #fcr.dirent_entry
|
|
sta [my_fcr],y
|
|
ldy #fcr.dirent_zone
|
|
sta [my_fcr],y
|
|
ldy #fcr.dirent_offset
|
|
sta [my_fcr],y
|
|
|
|
clc
|
|
exit
|
|
rts
|
|
endp
|
|
|
|
count_dirent_block procname
|
|
|
|
; 16-byte dirent entries -- 64 per block.
|
|
with dp, data
|
|
|
|
ldy #0
|
|
loop
|
|
lda [io_buffer],y
|
|
beq next
|
|
inc dirent_entry
|
|
next
|
|
; not 32-bit safe.
|
|
dec size
|
|
beq done
|
|
|
|
tya
|
|
clc
|
|
adc dirent_size
|
|
tay
|
|
cmp #1024
|
|
bcc loop
|
|
|
|
done
|
|
rts
|
|
|
|
endp
|
|
|
|
|
|
|
|
strlen procname
|
|
; strlen the dirent.
|
|
; will be 0-terminated unless if < dirent size.
|
|
|
|
lda data.dirent.inode
|
|
beq exit
|
|
|
|
ldx #2
|
|
short m
|
|
loop
|
|
lda data.dirent,x
|
|
beq zero
|
|
inx
|
|
cpx data.dirent_size
|
|
bcc loop
|
|
zero
|
|
long m
|
|
|
|
txa
|
|
dec a ; -2 for dirent.inode
|
|
dec a
|
|
|
|
exit
|
|
rts
|
|
endp
|
|
|
|
do_flags procname
|
|
with fst_parms
|
|
|
|
; $8000 for extended file, 0 for everything else.
|
|
lda #0
|
|
sta [param_blk_ptr],y
|
|
rts
|
|
endp
|
|
|
|
do_entry_num procname
|
|
with fst_parms
|
|
with data
|
|
|
|
lda dirent_entry
|
|
sta [param_blk_ptr],y
|
|
rts
|
|
endp
|
|
|
|
do_name_buffer_0 procname
|
|
with fst_parms
|
|
with dp
|
|
|
|
lda [param_blk_ptr],y
|
|
sta ptr
|
|
iny
|
|
iny
|
|
lda [param_blk_ptr],y
|
|
sta ptr+2
|
|
|
|
ora ptr
|
|
beq exit
|
|
|
|
|
|
copy_it
|
|
|
|
phx
|
|
jsr strlen
|
|
; strlen handles inode = 0
|
|
|
|
tax
|
|
tay
|
|
|
|
short m
|
|
|
|
sta [ptr]
|
|
|
|
; no need to dey since there is a length byte.
|
|
dex
|
|
bmi @done
|
|
|
|
@loop
|
|
lda data.dirent.name,x
|
|
sta [ptr],y
|
|
dey
|
|
dex
|
|
bpl @loop
|
|
@done
|
|
long m
|
|
plx
|
|
exit
|
|
rts
|
|
endp
|
|
|
|
do_name_buffer_1 procname
|
|
with fst_parms
|
|
with dp
|
|
|
|
lda [param_blk_ptr],y
|
|
sta ptr
|
|
iny
|
|
iny
|
|
lda [param_blk_ptr],y
|
|
sta ptr+2
|
|
|
|
ora ptr
|
|
beq exit
|
|
|
|
phx
|
|
jsr strlen
|
|
|
|
pha ; save
|
|
lda [ptr] ; total output buffer size
|
|
sec
|
|
sbc #4
|
|
bmi error
|
|
cmp 1,s
|
|
bcs ok
|
|
|
|
|
|
error_store_size
|
|
ldy #2
|
|
sta [ptr],y
|
|
|
|
error
|
|
pla
|
|
lda #buff_too_small
|
|
sta tool_error
|
|
plx
|
|
rts
|
|
|
|
ok
|
|
pla ; strlen
|
|
ldy #2
|
|
sta [ptr],y
|
|
|
|
tax
|
|
tay
|
|
iny ; skip gs/os string overhead
|
|
iny
|
|
iny
|
|
short m
|
|
dex
|
|
bmi @done
|
|
@loop
|
|
lda data.dirent.name,x
|
|
sta [ptr],y
|
|
dey
|
|
dex
|
|
bpl @loop
|
|
@done
|
|
long m
|
|
plx
|
|
|
|
exit
|
|
rts
|
|
endp
|
|
|
|
|
|
;
|
|
;
|
|
; new code....
|
|
; here's our big insight
|
|
; 1. base 1, displacement xxx is equivalent to stepping forward xxx entries.
|
|
; 2. base 2, displacement xxx is equivalent to base 0, displacement fcr.dirent_entry - displacement
|
|
; 2a. if displacement is 0, is equivalent to stepping forward 0 entries.
|
|
; 3. base 0, displacement xxx is equivalent to base 1 displacement xxx when fcr.dirent_entry = 0
|
|
;
|
|
; therefore the only special case is dirent_entry == 0 (since displacement 1 -> read entry 0)
|
|
;
|
|
;
|
|
find_absolute_dirent procname
|
|
with data
|
|
|
|
; if displacement > dirent_entry, we can re-use that info.
|
|
lda displacement
|
|
cmp dirent_entry
|
|
bcc no
|
|
|
|
sec
|
|
sbc dirent_entry
|
|
sta displacement
|
|
bra find_next_dirent
|
|
|
|
no
|
|
stz dirent_entry
|
|
stz dirent_zone
|
|
stz dirent_offset
|
|
|
|
bra find_next_dirent
|
|
endp
|
|
|
|
find_next_dirent proc
|
|
with data, dp
|
|
|
|
lda dirent_entry
|
|
beq @first
|
|
dec dirent_entry
|
|
bra @ok
|
|
@first
|
|
dec displacement
|
|
bmi eod
|
|
@ok
|
|
|
|
; make sure dir not empty (should never happen...)
|
|
lda size
|
|
beq eod
|
|
|
|
ldx dirent_zone
|
|
|
|
loop
|
|
lda disk_inode.zone,x
|
|
beq sparse ; should never happen...
|
|
phx ; save
|
|
jsr read_data_block
|
|
plx
|
|
bcs exit
|
|
|
|
; phx
|
|
; phy
|
|
; pha
|
|
; ~DebugHexDump <io_buffer, #1024
|
|
; pla
|
|
; ply
|
|
; plx
|
|
|
|
|
|
|
|
jsr find_dirent_block
|
|
bcc next
|
|
; a = 0 if it was found!
|
|
cmp #1
|
|
rts
|
|
|
|
next
|
|
inx
|
|
inx
|
|
stz dirent_offset
|
|
|
|
cpx #v1.NR_DZONES*2
|
|
bcs exit
|
|
bra loop
|
|
|
|
sparse
|
|
jsr sparse_dirent_block
|
|
bcs eod
|
|
bra next
|
|
|
|
|
|
found_it
|
|
;stx dirent_zone
|
|
;sty dirent_offset
|
|
clc
|
|
exit
|
|
rts
|
|
|
|
eod
|
|
lda #end_of_dir
|
|
sec
|
|
rts
|
|
endp
|
|
|
|
;
|
|
; returns:
|
|
; carry set on error or if found.
|
|
; a = 0 if found, or error.
|
|
;
|
|
; inputs y = dirent offset
|
|
find_dirent_block procname
|
|
with dp, data
|
|
|
|
ldy dirent_offset
|
|
loop
|
|
lda [io_buffer],y
|
|
beq next
|
|
|
|
inc dirent_entry
|
|
dec displacement
|
|
bmi found_it
|
|
|
|
next
|
|
dec size
|
|
beq eod
|
|
|
|
tya
|
|
clc
|
|
adc dirent_size
|
|
tay
|
|
cmp #1024
|
|
bcc loop
|
|
; not found ...
|
|
|
|
lda #0
|
|
clc
|
|
rts
|
|
|
|
eod
|
|
lda #end_of_dir
|
|
sec
|
|
rts
|
|
|
|
|
|
found_it
|
|
; we found our entry!!!
|
|
; copy it over.
|
|
|
|
stx dirent_zone
|
|
sty dirent_offset
|
|
; dirent_entry updated above.
|
|
|
|
ldx #0
|
|
@loop
|
|
lda [io_buffer],y
|
|
sta data.dirent,x
|
|
iny
|
|
iny
|
|
inx
|
|
inx
|
|
cpx dirent_size
|
|
bcc @loop
|
|
|
|
|
|
; update the fcr.
|
|
|
|
lda dirent_entry
|
|
ldy #fcr.dirent_entry
|
|
sta [my_fcr],y
|
|
|
|
lda dirent_offset
|
|
ldy #fcr.dirent_offset
|
|
sta [my_fcr],y
|
|
|
|
lda dirent_zone
|
|
ldy #fcr.dirent_zone
|
|
sta [my_fcr],y
|
|
|
|
lda #0
|
|
sec ; found!
|
|
rts
|
|
|
|
endp
|
|
|
|
|
|
strcmp procname
|
|
; clobbers ptr
|
|
|
|
; check if the name is even possible...
|
|
|
|
with dp, data
|
|
|
|
import target:GSString32
|
|
|
|
;~DebugSetTrace #1
|
|
|
|
iny ; skip inode
|
|
iny
|
|
tya
|
|
clc
|
|
adc io_buffer
|
|
sta ptr
|
|
lda #0
|
|
adc io_buffer+2
|
|
sta ptr+2
|
|
|
|
ldy #0
|
|
ldx target.length
|
|
|
|
short m
|
|
|
|
; y = offset
|
|
; x = length of target string.
|
|
loop
|
|
lda [ptr],y
|
|
beq eos
|
|
cmp target.text,y
|
|
bne no8
|
|
iny
|
|
dex
|
|
bpl loop
|
|
|
|
eos
|
|
long m
|
|
; if y == target.length, this is a match.
|
|
cpy target.length
|
|
bne no
|
|
|
|
yes
|
|
;~DebugSetTrace #0
|
|
clc
|
|
rts
|
|
|
|
|
|
no8
|
|
long m
|
|
no
|
|
;~DebugSetTrace #0
|
|
|
|
sec
|
|
rts
|
|
|
|
endp
|
|
|
|
sparse_dirent_block procname
|
|
; (not 32-bit safe)
|
|
|
|
; decrease size by the appropriate amount
|
|
; for a sparse block.
|
|
; (should probably never happen!)
|
|
|
|
; sets c if size <= 0
|
|
|
|
with data
|
|
|
|
lda dirent_size
|
|
cmp #32 ; linux? 32 dirents per block
|
|
beq @ok
|
|
lda #64 ; minix? 64 dirents per block
|
|
@ok
|
|
eor #$ffff
|
|
sec
|
|
adc size
|
|
sta size
|
|
bmi eod
|
|
beq eod
|
|
clc
|
|
rts
|
|
eod
|
|
sec
|
|
rts
|
|
|
|
endp
|
|
|
|
find_entry_by_name procname export
|
|
|
|
; scan the directory and search by name...
|
|
|
|
with dp
|
|
with data
|
|
|
|
import target:GSString32
|
|
|
|
|
|
jsr init
|
|
lda size
|
|
beq fnf
|
|
bmi fnf
|
|
|
|
|
|
; make sure the name is valid.
|
|
|
|
ldx target.length
|
|
beq fnf
|
|
|
|
; if dirent_size < target.length, it can't be found.
|
|
; should do this sooner.
|
|
lda data.dirent_size
|
|
dec a
|
|
dec a
|
|
cmp target.length
|
|
bcc fnf
|
|
|
|
|
|
ldx #0
|
|
zone_loop
|
|
; x = dirent_zone
|
|
stx dirent_zone
|
|
lda disk_inode.zone,x
|
|
beq sparse
|
|
|
|
jsr read_data_block
|
|
bcc @ok
|
|
rts
|
|
|
|
@ok
|
|
ldy #0
|
|
|
|
dirent_loop
|
|
; y = dirent offset
|
|
sty dirent_offset
|
|
|
|
lda [io_buffer],y
|
|
beq next_dirent
|
|
sta inode ; optomistic...
|
|
|
|
jsr strcmp
|
|
bcs next_dirent
|
|
|
|
; found it!
|
|
lda #0
|
|
clc
|
|
rts
|
|
|
|
next_dirent
|
|
|
|
dec size
|
|
beq fnf
|
|
|
|
lda dirent_offset
|
|
clc
|
|
adc dirent_size
|
|
tay
|
|
cmp #1024
|
|
bcs next_zone
|
|
bra dirent_loop
|
|
|
|
|
|
next_zone
|
|
ldx dirent_zone
|
|
inx
|
|
inx
|
|
cpx #v1.NR_DZONES*2
|
|
bcc zone_loop
|
|
; all out of zones -> not found!
|
|
|
|
|
|
fnf
|
|
stz inode
|
|
lda #file_not_found
|
|
sec
|
|
rts
|
|
|
|
sparse
|
|
; sparse block. jump to the next zone, decrement size appropriately.
|
|
jsr sparse_dirent_block
|
|
bcs fnf
|
|
bra next_zone
|
|
|
|
endp
|
|
|
|
|
|
end |