minix.fst/get_file_info.aii
2015-08-26 11:58:17 -04:00

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