mirror of
https://github.com/ksherlock/minix.fst.git
synced 2024-12-27 06:29:15 +00:00
628 lines
8.1 KiB
Plaintext
628 lines
8.1 KiB
Plaintext
|
|
string asis
|
|
|
|
include 'gsos.equ'
|
|
include 'minix.equ'
|
|
include 'records.equ'
|
|
|
|
include 'fst.equ'
|
|
|
|
include 'fst.macros'
|
|
|
|
include 'M16.Debug'
|
|
|
|
|
|
|
|
|
|
entry path_to_inode
|
|
entry load_inode
|
|
entry find_file
|
|
entry volume_by_name
|
|
entry vstrcmp
|
|
|
|
import id_disk
|
|
import device_read
|
|
|
|
|
|
import disk_inode:v1_inode
|
|
import disk_super:v1_super
|
|
|
|
data record
|
|
|
|
path_offset ds.w 1
|
|
more ds.w 1
|
|
|
|
endr
|
|
|
|
get_file_info procname export
|
|
|
|
with fst_parms
|
|
with dev_parms
|
|
with dp
|
|
|
|
;~DebugSetTrace #1
|
|
|
|
;brk $ea
|
|
jsr path_to_inode
|
|
bcs exit
|
|
|
|
jsr load_inode
|
|
bcs exit
|
|
|
|
|
|
|
|
|
|
|
|
;pha ; space
|
|
;~DebugSetTrace #0
|
|
;pla ; prev value
|
|
|
|
|
|
lda <call_class
|
|
beq class0
|
|
|
|
class1
|
|
lda [param_blk_ptr] ; pcount
|
|
dec a
|
|
asl a ; x 2
|
|
asl a ; x 4
|
|
tax
|
|
dispatch file_info_dcb_1
|
|
lda tool_error
|
|
cmp #1
|
|
rtl
|
|
|
|
class0
|
|
ldx #file_info_dcb_0_size-4
|
|
dispatch file_info_dcb_0
|
|
lda tool_error
|
|
cmp #1
|
|
rtl
|
|
|
|
exit
|
|
rtl
|
|
|
|
import do_ignore
|
|
import do_access
|
|
import do_create_date_time, do_mod_date_time
|
|
import do_create_date_time_0, do_mod_date_time_0
|
|
import do_option_list
|
|
import do_file_type, do_aux_type, do_storage_type
|
|
import do_eof, do_blocks, do_r_eof, do_r_blocks
|
|
|
|
file_info_dcb_0
|
|
dc.w $00, do_ignore ; pathname
|
|
dc.w $04, do_access
|
|
dc.w $06, do_file_type
|
|
dc.w $08, do_aux_type
|
|
dc.w $0c, do_storage_type
|
|
dc.w $0e, do_create_date_time_0
|
|
dc.w $12, do_mod_date_time_0
|
|
dc.w $16, do_blocks
|
|
file_info_dcb_0_size equ *-file_info_dcb_0
|
|
|
|
file_info_dcb_1
|
|
;dc.w $00, do_ignore ; pCount
|
|
dc.w $02, do_ignore ; pathname
|
|
dc.w $06, do_access
|
|
dc.w $08, do_file_type
|
|
dc.w $0a, do_aux_type
|
|
dc.w $0e, do_storage_type
|
|
dc.w $10, do_create_date_time
|
|
dc.w $18, do_mod_date_time
|
|
dc.w $20, do_option_list
|
|
dc.w $24, do_eof
|
|
dc.w $28, do_blocks
|
|
dc.w $2c, do_r_eof
|
|
dc.w $30, do_r_blocks
|
|
endp
|
|
|
|
|
|
|
|
load_inode procname export
|
|
;
|
|
; loads inode into disk_inode.
|
|
;
|
|
; inputs :
|
|
; my_vcr
|
|
; inode
|
|
; device
|
|
;
|
|
; outputs :
|
|
; disk_inode
|
|
; error in a/c
|
|
|
|
; todo -- check if inode # is valid?
|
|
; todo -- check if bit set in imap?
|
|
|
|
|
|
with fst_parms
|
|
with dev_parms
|
|
with dp
|
|
|
|
ldy #vcr.first_inode_block
|
|
lda [my_vcr],y
|
|
asl a ; x 2
|
|
sta dev_blk_num
|
|
;lda #0
|
|
;rol a
|
|
;sta dev_blk_num+2
|
|
stz dev_blk_num+2 ; should be less than 0xffff inode blocks!
|
|
|
|
; 32 inodes per block.
|
|
; however, I'd rather read half-block chunks, with means
|
|
; 16 inodes per half-block.
|
|
lda inode
|
|
dec a ; inode 1 is offset 0.
|
|
lsr a ; / 2
|
|
lsr a ; / 4
|
|
lsr a ; / 8
|
|
lsr a ; / 16
|
|
;lsr a ; / 32
|
|
|
|
clc
|
|
adc dev_blk_num
|
|
sta dev_blk_num
|
|
|
|
lda #512
|
|
;sta dev_blk_size
|
|
sta dev_req_cnt
|
|
|
|
; dev_num must already be set up.
|
|
;lda device ;;;;
|
|
;sta dev_num
|
|
|
|
jsr device_read
|
|
bcc ok
|
|
rts
|
|
ok
|
|
|
|
; find the inode...
|
|
lda inode
|
|
dec a ; inode 1 is offset 0.
|
|
and #$0f
|
|
; multiply by 32
|
|
asl a ; x 2
|
|
asl a ; x 4
|
|
asl a ; x 8
|
|
asl a ; x 16
|
|
asl a ; x 32
|
|
clc
|
|
adc #v1_inode.__sizeof-2
|
|
tay
|
|
|
|
;adc io_buffer
|
|
;sta ptr
|
|
;lda #0
|
|
;adc io_buffer+2
|
|
;sta ptr+2
|
|
|
|
; copy to dp
|
|
ldx #v1_inode.__sizeof-2
|
|
@loop
|
|
lda [io_buffer],y
|
|
sta disk_inode,x
|
|
dey
|
|
dey
|
|
dex
|
|
dex
|
|
bpl @loop
|
|
|
|
lda #0
|
|
clc
|
|
rts
|
|
|
|
|
|
endp
|
|
|
|
;
|
|
; sets inode, parent_inode, disk_inode,
|
|
; if file not present but path is otherwise, ok (eg, create),
|
|
; parent inode and disk_inode will be valid for the parent directory.
|
|
;
|
|
; uses path1, dev1, span1.
|
|
;
|
|
|
|
|
|
;
|
|
; After GS/OS expands prefixes, there are two path types
|
|
; 1. device root (.dev:path)
|
|
; 2. path root (:volume:path)
|
|
;
|
|
; in the case of 1, verify the device is a minix volume, create
|
|
; the vcr (if necessary) and proceed from there.
|
|
;
|
|
; in the case of 2, gs/os will check for a vcr with the volume
|
|
; name and, if found, give the FST a first shot at handling it.
|
|
; if the FST doesn't claim it, or no vcr is found, all FSTs will
|
|
; be called until it's claimed.
|
|
;
|
|
; fst_parms.vcr will not be populated even if GS/OS previously found
|
|
; it.
|
|
;
|
|
|
|
|
|
path_to_inode procname export
|
|
with dp,fst_parms
|
|
|
|
|
|
path equ path1_ptr
|
|
dev_num equ dev1_num
|
|
span equ span1
|
|
|
|
stz inode
|
|
lda #1
|
|
sta parent_inode
|
|
|
|
lda path_flag
|
|
and #$4000
|
|
bne check_path
|
|
|
|
|
|
no_path
|
|
; device only (eg, .dev1 )
|
|
;
|
|
lda #1
|
|
sta inode
|
|
|
|
lda dev_num
|
|
beq bps
|
|
;sta device
|
|
jmp id_disk
|
|
; returns
|
|
bps
|
|
lda #bad_path_syntax
|
|
sec
|
|
exit
|
|
rts
|
|
|
|
check_path
|
|
|
|
; linux allows a 30-char name. minix is 14 char
|
|
; will check for minix later.
|
|
lda span
|
|
cmp #v1L.DIRSIZE+1
|
|
bcs bps
|
|
|
|
; but is it relative?
|
|
|
|
ldy #2
|
|
lda [path],y
|
|
and #$00ff
|
|
cmp #':'
|
|
beq absolute
|
|
|
|
lda #1
|
|
sta inode
|
|
|
|
lda dev_num
|
|
beq bps
|
|
;sta device
|
|
jsr id_disk
|
|
bcs exit
|
|
lda #2
|
|
sta data.path_offset ; skip past gs-os length word
|
|
brl find_file ; will rts.
|
|
;
|
|
|
|
absolute
|
|
;
|
|
; worst case ...
|
|
; 1. extract the volume name.
|
|
; 2. call find_vcr to find it by name
|
|
; 3. if that fails, scan all devices.
|
|
|
|
|
|
jsr volume_by_name
|
|
_rts.cs
|
|
|
|
brl find_file
|
|
|
|
endp
|
|
|
|
entry skip_colon
|
|
skip_colon proc
|
|
;returns carry set if end of path.
|
|
|
|
with dp, data
|
|
path equ fst_parms.path1_ptr
|
|
|
|
|
|
ldy path_offset
|
|
short m
|
|
@loop
|
|
lda [path],y
|
|
beq zero
|
|
cmp #':'
|
|
bne done
|
|
iny
|
|
bra @loop
|
|
done
|
|
lda #':'
|
|
sta more
|
|
sty path_offset
|
|
long m
|
|
clc
|
|
rts
|
|
zero
|
|
long m
|
|
stz more
|
|
sty data.path_offset
|
|
sec
|
|
rts
|
|
endp
|
|
|
|
find_file procname
|
|
|
|
with dp
|
|
with data
|
|
|
|
import find_entry_by_name
|
|
|
|
path equ fst_parms.path1_ptr
|
|
dev_num equ fst_parms.dev1_num
|
|
span equ fst_parms.span1
|
|
|
|
import target:GSString32
|
|
|
|
stz more
|
|
|
|
; we always need to load inode 1
|
|
lda #1
|
|
sta inode
|
|
jsr load_inode
|
|
_rts.cs
|
|
|
|
|
|
dir_loop
|
|
|
|
|
|
; get a path component.
|
|
|
|
|
|
; 1. check for a null path.
|
|
jsr skip_colon
|
|
bcs done
|
|
|
|
lda inode
|
|
sta parent_inode
|
|
|
|
ldx #0
|
|
ldy path_offset
|
|
short m
|
|
path_loop
|
|
lda [path],y
|
|
beq eop
|
|
cmp #':'
|
|
beq eop
|
|
sta target.text,x
|
|
inx
|
|
iny
|
|
bra path_loop
|
|
eop
|
|
sta more
|
|
long m
|
|
stx target.length
|
|
sty path_offset
|
|
; a = ':' or 0 ... worry about which later!
|
|
|
|
; target is valid, inode is valid, is target in inode?
|
|
|
|
;~DebugHexDump #target, #34
|
|
|
|
|
|
jsr find_entry_by_name
|
|
bcc @ok
|
|
; may be file_not_found, may be path_not_found.
|
|
ldx more
|
|
beq @exit
|
|
lda #path_not_found
|
|
@exit
|
|
sec
|
|
rts
|
|
|
|
@ok
|
|
; inode, has been updated.
|
|
jsr load_inode
|
|
_rts.cs
|
|
|
|
lda more
|
|
beq done
|
|
|
|
; more to go...
|
|
|
|
; this is a directory, right?
|
|
lda disk_inode.mode
|
|
and #S_IFMT
|
|
cmp #S_IFDIR
|
|
beq dir_loop
|
|
lda #path_not_found
|
|
sec
|
|
rts
|
|
|
|
done
|
|
clc
|
|
rts
|
|
|
|
endp
|
|
|
|
volume_by_name procname
|
|
;
|
|
; extract the volume name from path1_ptr and find (or create) a vcr.
|
|
;
|
|
;
|
|
|
|
with dp
|
|
with data
|
|
|
|
path equ fst_parms.path1_ptr
|
|
|
|
import target:GSString32
|
|
|
|
; copy volume name to target.
|
|
; leading : is NOT included.
|
|
|
|
ldx #0
|
|
ldy #3
|
|
short m
|
|
@loop
|
|
lda [path],y
|
|
beq done
|
|
cmp #':'
|
|
bne @next
|
|
iny
|
|
bra done
|
|
@next
|
|
sta target.text,x
|
|
inx
|
|
iny
|
|
bra @loop
|
|
done
|
|
|
|
long m
|
|
sty path_offset
|
|
stx target.length
|
|
|
|
ldx #target
|
|
ldy #^target
|
|
lda #0
|
|
jsl find_vcr
|
|
bcs no_vcr
|
|
|
|
; store it for later...
|
|
stx ptr
|
|
sty ptr+2
|
|
|
|
jsl deref
|
|
stx my_vcr
|
|
sty my_vcr+2
|
|
|
|
ldy #vcr.fst_id
|
|
lda [my_vcr],y
|
|
cmp #fst_id
|
|
bne no_vcr
|
|
|
|
; there is a vcr and it's a minix vcr.
|
|
; 1. should do a case-sensitive name check.
|
|
; 2. if the volume is marked as swapped, we need to
|
|
; re-scan devices.
|
|
; 3. if the volume is not swapped, we need to verify
|
|
; the disk didn't switch on us.
|
|
|
|
ldy #vcr.status
|
|
lda [my_vcr],y
|
|
and #vcr_swapped
|
|
bne no_vcr
|
|
|
|
ldy #vcr.device
|
|
lda [my_vcr],y
|
|
jsr id_disk
|
|
bcs no_vcr
|
|
|
|
;
|
|
; I suppose reading a block could alloc memory and invalidate the vcr...
|
|
;
|
|
|
|
ldx ptr
|
|
ldy ptr+2
|
|
|
|
jsl deref
|
|
stx my_vcr
|
|
sty my_vcr+2
|
|
|
|
; check the volume name here...
|
|
|
|
jsr vstrcmp
|
|
bcs no_vcr
|
|
rts
|
|
|
|
|
|
no_vcr
|
|
; no vcr on file... scan all devices to find the volume.
|
|
stz my_vcr
|
|
stz my_vcr+2
|
|
|
|
stz device
|
|
|
|
@loop
|
|
lda device
|
|
inc a
|
|
sta device
|
|
jsr id_disk
|
|
|
|
bcs @error_check
|
|
|
|
; check if the volume name matches...
|
|
jsr vstrcmp
|
|
bcs @loop
|
|
|
|
; match! hooray!
|
|
clc
|
|
rts
|
|
|
|
@error_check
|
|
cmp #dup_volume
|
|
beq @error
|
|
cmp #invalid_dev_num
|
|
bne @loop
|
|
lda #vol_not_found
|
|
@error
|
|
sec
|
|
rts
|
|
device
|
|
ds.w 1
|
|
endp
|
|
|
|
vstrcmp procname
|
|
|
|
import target:GSString32
|
|
|
|
; case-sensitive strcmp for volume name
|
|
;
|
|
; target does not have a leading :
|
|
; vcr.vname has a leading :
|
|
;
|
|
|
|
with dp
|
|
|
|
|
|
lda target.length
|
|
inc a ; + 1 for :
|
|
|
|
ldy #vcr.vname.length
|
|
cmp [my_vcr],y
|
|
bne fail
|
|
|
|
lda #vcr.vname.text
|
|
clc
|
|
adc target.length
|
|
tay
|
|
|
|
ldx target.length
|
|
dex
|
|
|
|
short m
|
|
@loop
|
|
lda target.text,x
|
|
cmp [my_vcr],y
|
|
bne fail8
|
|
dey
|
|
dex
|
|
bpl @loop
|
|
|
|
;success
|
|
long m
|
|
clc
|
|
rts
|
|
|
|
|
|
fail8
|
|
long m
|
|
fail
|
|
sec
|
|
rts
|
|
|
|
endp
|
|
|
|
end
|