 lib environment
 sttl Pathname Handler
 pag
 name pathnam
 global pthnm,pthnmc

*
* pthnm
*
* Look up the path name pointed at by 'ucname'.
* On entry, B contains a flag which if 0, means
* get the name from the system space, else get
* it from the user space.  On exit, X points to
* an fdn representing the file named.  If X is 0,
* no file was found and uerror may be set.
* Also, B will be non zero if a name was processed.
* 'pthnmc' is the entry for file creation.
*
P_TRC equ 0

pthnmc bsr pthnm process path name
cpthnm cmpx #0 no file found?
 bne pthnc2 x!=0 if have file
 tst uerror error?
 bne pthnc2
 pshs b,x save args
 ldx ulstdr get last dir fdn
 ldb #FACUW check write perm
 lbsr tstprm
 puls b,x reset args
 beq pthnc2 perm ok?
 ldx ulstdr get dir fdn
 lbsr frefdn free the fdn
 ldx #0 set error
 clrb
pthnc2 rts return

pthnm
 if P_TRC
 jsr ptrace
 fcc $d,'pthnm',0
 endif
 clra set up stack
 pshs d
 ldx ucrdir get current dir fdn
 stx ulstdr save last dir
 pshs x save on stack
 lbsr gpchr get next path char
 ldx 0,s reset fdn pointer
 cmpa #'/ is it slash?
 bne pthnm2
 ldx rtdir make root dir start
 stx 0,s set on stack
 stx ulstdr save last dir
pthnm2
 if P_TRC
 jsr ptrace
 fcc $d,'pthnm2',0
 endif
 pshs a save last character
 ldy fnumbr,x get fdn number
 ldd fdevic,x get fdn device
 lbsr asnfdn access the fdn
 cmpx #0 fdn found?
 lbeq pfnde2 if not error!
 lda 0,s get last character
 ldb 4,s get sys/user flag
 lbsr eatsl eat all slashes
 sta 0,s save last character

 pag

*
* pntry
*
* Process a pathname entry.  Stack has data from
* pthnm.  At this time, we have an fdn of a dir
* and will eventually search it for the next name.
*

pntry
 if P_TRC
 jsr ptrace
 fcc $d,'pntry',0
 endif
 lda 0,s get last character
 lbeq pfndr if 0, we are done
 ldx 1,s get current dir fdn
 lda fmode,x check modes
 bita #FSDIR is it a directory?
 bne pntry2 if it is, ok
 lda #ENDR else set error
 sta uerror
 lbra pfnde go exit
pntry2
 if P_TRC
 jsr ptrace
 fcc $d,'pntry2',0
 endif
 ldb #FACUE set permission pattern
 lbsr tstprm test permission bits
 lbne pfnde error?
 ldb 4,s get sys/user flag
 lda 0,s get the last character
 lbsr gtnam get path name component
 ldb 4,s get io flag
 lbsr eatsl eat all slashes
 sta 0,s save last character
 inc 3,s set name found flag
 ldd #0 init file pointers
 std uipos2 pos to file beginning
 std uipos
 std ufdel set first deleted to null
 clr uiosp set to system space
 ldx 1,s get fdn
 ldd fsize+2,x get dir size
 lsra divide size by the size
 rorb of a directory entry
 lsra this is done by shifting
 rorb right 4 times (div by 16)
 lsra
 rorb
 lsra
 rorb all done now
 std uicnt save this as count
 ldy #0 set init buffer ptr

 pag

*
* psrch
*
* Search a directory for a pathname component.  The
* component is in 'uwrkbf'.  This routine is entered
* from above only.
*

psrch
 pshs y save buffer ptr
psrch1
 if P_TRC
 jsr ptrace
 fcc $d,'psrch1',0
 endif
 ldd uicnt get file count
 beq psrch6 if 0, we are done
 ldb uipos2+1 get position
 bne psrch4 (we are checking for
 lda uipos2 buffer boundary) (512 bytes)
 bita #1
 bne psrch4
 ldy 0,s get old buffer ptr
 beq psrch2 if 0, we dont have one
 lbsr freebf free up old buffer
psrch2
 if P_TRC
 jsr ptrace
 fcc $d,'psrch2',0
 endif
 ldu 3,s get current fdn
 ldd fdevic,u get device number
 pshs d save it
 ldb uipos2 calc block number
 clra from position>>9
 lsrb (thats what we just did!)
 tfr d,x put block in x
 ldy #0 hi block is 0
 if P_TRC
 jsr ptrace
 fcc '-mapfil',0
 endif
 lbsr mapfil get physical block number
 puls d get device number
 if P_TRC
 jsr ptrace
 fcc '-rdbuf',0
 endif
 lbsr rdbuf read in block
 sty 0,s save buffer ptr
 tst uerror any errors?
 bne psrch6
psrch4
 if P_TRC
 jsr ptrace
 fcc $d,'psrch4',0
 endif
 ldx 0,s get buffer hdr
 lbsr cpynm copy next name to 'udname'
 ldd uipos2 get position
 addd #DIRSIZ+2 add in bytes xfrd
 std uipos2 save new pos
 ldd uicnt dec the file count
 subd #1 by one file
 std uicnt save new count
 bsr updel update deleted file marker
 beq psrch1 is it deleted?
 lbsr cmpnm compare 'udname' to 'uwrkbf'
 bne psrch1 if not same, loop
 bra pfnd we found it!
psrch6
 if P_TRC
 jsr ptrace
 fcc $d,'psrch6',0
 endif
 ldy 0,s++ get buffer ptr
 beq pfnde4 is it set?
 lbsr freebf free it if set
 bra pfnde4 go exit

 pag

*
* pfnd
*
* We get here if the path name component was found.
* If no more name characters left, exit, else
* repeat loop looking for next element.
*

pfnd
 if P_TRC
 jsr ptrace
 fcc $d,'pfnd',0
 endif
 ldy 0,s++ get buffer header
 beq pfnd2 is it null?
 lbsr freebf free the buffer
pfnd2
 if P_TRC
 jsr ptrace
 fcc $d,'pfnd2',0
 endif
 lda 0,s check last character
 bne pfnd4
 ldd 5,s check if unlinking
 cmpd #unlinr
 beq pfndr if so, return
pfnd4
 if P_TRC
 jsr ptrace
 fcc $d,'pfnd4',0
 endif
 ldx 1,s get fdn pointer
 lbsr frefdn free up the fdn
 ldx 1,s get the fdn again
 ldd fdevic,x get device number
 ldy ufdn get new fdn number
 lbsr asnfdn assign an fdn entry
 stx 1,s save new fdn pointer
 stx ulstdr save last dir
 beq pfnde2 if 0, error
 lbra pntry repeat search

*
* pathname lookup exit points
*

pfndr ldx 1,s get fdn pointer
pfndr2 ldb 3,s get name flag
 leas 5,s fix stack
 if P_TRC
 jsr ptrace
 fcc $d,'pfndr2',0
 endif
 rts return
pfnde ldx 1,s get fdn ptr
 lbsr frefdn free up the fdn
pfnde2 ldx #0 set null fdn
 bra pfndr2
pfnde4 tst uerror any errors?
 bne pfnde if so - exit
 lda 0,s check last character
 bne pfnde6 error if not 0
 ldd 5,s check where came from
 cmpd #cpthnm creating file?
 beq pfnde2 if so, leave fdn
 bra pfnde else remove fdn
pfnde6 lda #EMSDR set missing dir error
 sta uerror
 bra pfnde do error exit


 pag

*
* updel
*
* Update the first deleted directory marker 'ufdel'.
* Return an 'eq' status if the current entry is a
* deleted entry.
*

updel ldd ufdn get fdn number
 bne updel2 if != 0, then not del
 ldd ufdel is first del set?
 bne updel1 if so, leave it
 ldd uipos2 get current position
 subd #DIRSIZ+2 pt to beginning of entry
 std ufdel set first deleted
updel1 sez set 'eq' status
updel2 rts return


*
* eatsl
*
* Eat all successive slashes ('/') found in the
* current pathname.  Return with the last character
* read in A.
*

eatsl cmpa #'/ is char a slash?
 bne eatsl2
 pshs b save space flag
 bsr gpchr get next path char
 puls b
 bra eatsl repeat
eatsl2 rts return


 pag

*
* gpchr
*
* Get the next pathname character.  On entry,
* B contains a flag.  If it is 0, get the character
* from the system space, else from the user.
* 'ucname' has the pointer to the character string.
*

gpchr ldx ucname get string pointer
 tstb system space?
 bne gpchr2 if !=0 then user
 lda 0,x+ get the character
 stx ucname save new ptr
 rts return
gpchr2 lbsr gtubyt get user byte
 tfr b,a put char in a
 leax 1,x bump pointer
 stx ucname save new ptr
 rts return


*
* cmpnm
*
* Compare the current path name component with
* the name just read in from the directory.
* This compares the contents of 'uwrkbf' and
* 'udname'.  Return 'eq' status if equal.
*

cmpnm ldb #DIRSIZ/2 set up count
 pshs b
 ldx #uwrkbf set first ptr
 ldy #udname set second ptr
cmpnm2 ldd 0,x++ get word
 cmpd 0,y++ compare it
 bne cmpnm4 do they match?
 dec 0,s dec the count
 bne cmpnm2 loop til done
cmpnm4 puls b,pc return


 pag

*
* gtnam
*
* Get the neat directory name from the current
* directory.  On entry, B is 0 if the name is
* coming from the system space, or 1 if user
* space.  The name is read into 'uwrkbf' and
* is null padded on the right.  The last character
* read is returned in A.
*

gtnam ldy #uwrkbf point to work buffer
 pshs b save sys/user flag
 ldb #DIRSIZ-1 get character count
 pshs b save on stack
 ldb 1,s reset flag
 sta 0,y+
gtnam2 bsr gpchr get name character
 cmpa #0 is it null?
 beq gtnam6
 cmpa #'/ is it slash
 beq gtnam6
 sta 0,y+ store the character in buffer
 dec 0,s dec the counter
 bne gtnam2 loop if not done
gtnam4 bsr gpchr get next character
 cmpa #0 is it null?
 beq gtnam5
 cmpa #'/ is it slash?
 bne gtnam4 if not, must eat rest
gtnam5 leas 2,s clean up stack
 rts return
gtnam6 ldb 0,s get count
 beq gtnam8 all done?
gtnam7 clr 0,y+ zero rest of buffer
 decb dec the count
 bne gtnam7
gtnam8 leas 2,s clean up stack
 rts return


 pag

*
* cpynm
*
* Copy name from buffer pointed at by X to the
* udname area.
*

cpynm ldd uipos2 get position
 anda #1 calculate buffer offset
 tfr d,u set offset in u
 ldy #ufdn point to user area
 ldd #DIRSIZ+2 set byte count
 lbra cpybts go do copy
