;*****************************************************
;	Subroutine - lib$fid_to_name
;	Author - Bruce Ellis
;	Synopsis - converts a file id to file name.  Also
;	returns a count of the number of mapping pointers
;	in the file header.
;	inputs:
;		4(ap) - descriptor for file name
;		8(ap) - address of file id
;		12(ap) - address of descriptor for the file string
;		16(ap) - address of location to return char count
;		20(ap) - address to return the count of mapping pointers
;****************************************************************

;macros

	.macro	c_s	?lab
	blbs	r0,lab
	$exit_s	r0
lab:
	.endm
;includes
	.library	/sys$library:lib.mlb/
	$hm2def
	$fh2def
	$fm2def
	$fi2def
ASSUME	fi2$t_filename eq 0
	.psect	$$banana_imp_data,wrt,noshr
c:	.blkl	1	;channel for disk
	$fibdef
fib:	.blkb	fib$k_length	;file information block for index file
fid:	.word	1,1,0		;file id of index file
did:	.word	0,0,0	
fibd:	.long	42		;descriptor for fib
	.address	fib
BLOCK:	.BLKB	512		;Block to store headers/home block
block2:	.blkb	512		;block to store extension headers
IOST:	.blkq	1		;io status block
file_name:	
	.blkb	fi2$s_filenamext+fi2$s_filename		;file name local
							;storage
dirs:	.blkb	<fi2$s_filenamext+fi2$s_filename>*8	;directory name
							;local storage
full_spec:
	.blkb	<fi2$s_filename+fi2$s_filenamext>*10	;full file spec
							;local storage
siz:	.blkl	1				;local 
new_fid:
	.blkw	6
ptr_count:
	.long	1
	.psect	$$banana_code,nowrt,shr
	

	.entry	lib$fid_to_name,^m<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>
	movl	12(ap),r8		;Get the address of user descriptor
	movzwl	(r8),r6			;Get the size of the buffer
	movl	4(r8),r8		;get address of buffer
	movc5	#0,siz,#^a/ /,r6,(r8)	;zero the buffer
	movc3	#6,@8(ap),new_fid	;copy the file id to local storage
	$assign_s	chan=c,devnam=@4(ap)	;assign chan to disk device
	c_s
	moval	fib,r6			;Set up file information block
	movl	#0,fib$l_acctl(r6)	;null
	movb	#0,fib$b_wsize(r6)	;null
	movc3	#6,fid,fib$w_fid(r6)	;indexf fid
	movc3	#6,did,fib$w_did(r6)	;null
	movl	#0,fib$l_wcc(r6)	;null
	movw	#0,fib$w_nmctl(r6)	;null
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;Open the Index file
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
	$qiow_s	chan=c,func=#io$_access!io$m_access,-
		p1=fibd
	c_s
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;Read the home block
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
	$qiow_s	chan=c,func=#io$_readvblk,iosb=IOST,-
		p1=BLOCK,p2=#512,p3=#2
	c_s
	blbs	IOST,10$		;Make sure we read it
	brw	EOF
10$:	movzwl	hm2$w_cluster+block,r8	;Get the volume cluster factor
	mull2	#4,r8			;times 4 gets to the index bitmap
	addw2	hm2$w_ibmapsize+block,r8	;plus bitmap size gets
out:						;us the the first header
	movl	r8,r10			;r10 points to VBN for first header
	movzwl	new_fid,r3		;get file number
	addl	r3,r8			;add to first header vbn to get
					;header for file we are looking for

;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;Read the header
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
	$qiow_s	chan=c,func=#io$_readvblk,iosb=IOST,-
		p1=BLOCK,p2=#512,p3=r8
	c_s
	cmpw	block+fh2$w_fid_seq,new_fid+2	;same sequence number?
	beql	same_seq
	brw	EOF				;Do not process file name 
						; if different sequence #s
same_seq:
;***************************************
;	count mapping pointers
;***************************************
	moval	block,r9			;save block location
	clrl	ptr_count
next_ext_header:
	movzbl	fh2$b_mpoffset(r9),r2		;get # of words to map area
	mull2	#2,r2				;Locate offset to the map area
	addl2	r9,r2				;get base of map area
next_mapping_ptr:
	movw	(r2)+,r3			;get first mapping ptr
	beql	no_more_pointers		;if 0 done
	extzv	#fm2$v_format,#fm2$s_format,r3,r4	;determine ptr type
	mull2	#2,r4				;determine # of words to skip
	addl	r4,r2				;point to next mapping ptr
	incl	ptr_count			;one more pointer
	brw	next_mapping_ptr
no_more_pointers:
	movw	fh2$w_ext_fid(r9),r3		;check for an extension header
	beql	done_with_pointers		;if none get out
	addl3	r3,r10,r8			;else read the header
	$qiow_s	chan=c,func=#io$_readvblk,iosb=IOST,-
		p1=BLOCK2,p2=#512,p3=r8
	c_s
	moval	block2,r9			;point to extension header
	brw	next_ext_header
done_with_pointers:	
	movl	ptr_count,@20(ap)		;return count of pointers
	movzbl	block+fh2$b_idoffset,r7		;locate the ident area
	mull2	#2,r7				;

;*******************************************
;Copy the file name and extended name portion to file name storage
;*******************************************
	movc3	#fi2$s_filename,block(r7),file_name	
	movc3	#fi2$s_filenamext,<fi2$t_filenamext+block>(r7),-
		file_name+fi2$s_filename	
	
	clrl	r11		;clear nesting level counter
	clrl	r7		;clear byte offset into directory array
	clrl	siz		;clear out the size of the string
next_dir:
	movzwl	BLOCK+fh2$w_backlink,R9	;get the backlink dir fid
	addl3	R9,R10,R8		;get dir VBN
;*******************************************
;Read back one directory level
;*******************************************
	$qiow_s	chan=c,func=#io$_readvblk,iosb=IOST,-
		p1=BLOCK,p2=#512,p3=r8
	c_s
	movzbl	block+fh2$b_idoffset,r5	;Get the ident area word offset
	mull2	#2,r5			;locate the ident area
;********************************************
;Copy the directory file name into the directory array
;********************************************
	movc3	#fi2$s_filename,block(r5),dirs(r7)	
	movc3	#fi2$s_filenamext,<block+fi2$t_filenamext>(r5),-
		<dirs+fi2$s_filename>(r7)
	addl	#<fi2$s_filenamext+fi2$s_filename>,r7 	;Point to next dir
							; element in dir
							;array
	incl	r11			;increment nesting level counter
	cmpw	fh2$w_backlink+BLOCK,#4	;If at the Master file directory
					;backlink we are done looking up
					;file specs
	bneq	next_dir		;Else get next higher directory
	moval	full_spec,r8		;R8 points to storage for the 
					;fully formed file spec
	movb	#^A/[/,(r8)+		;begin directory character to string
	incl	siz			;size of string +=1
	decl	r11			;nest level -=1
	pushl	r11			;save nesting level

;*************************************************
;Locate top level directory specification
;*************************************************
	mull2	#<fi2$s_filenamext+fi2$s_filename>,r11	
	movl	r11,r7			;r7 to point to top level
	popl	r11			;restore r11
get_dir:
;*************************************************
;locate the .DIR extension in the directory file name
;*************************************************
	locc	#^a/./,#<fi2$s_filenamext+fi2$s_filename>,dirs(r7)
;*************************************************
;Calculate the size of the string to the "."
;*************************************************
	subl3	r0,#<fi2$s_filenamext+1+fi2$s_filename>,r0
	pushl	r0			;save the size
	movc3	r0,dirs(r7),(r8)	;copy the directory string thru "."
	popl	r0			;restore size
	addl	r0,r8			;update address of string buffer
	addl	r0,siz			;update the size of the string
	decl	r11			;depth level -=1
	blss	out_dir			;if outta directories break loop
	subl	#<fi2$s_filenamext+fi2$s_filename>,r7	;else update the
					;  dir array pointer
	brw	get_dir			;and get the next directory

out_dir:
	decl	r8			;skip back to overwrite last "."
	movb	#^a/]/,(r8)+		; with a "]"
;*************************************************
;calculate the size of the file name (not a counted string)
;by locating the first " "
;*************************************************
	locc	#^a/ /,#<fi2$s_filenamext+fi2$s_filename>,file_name
	subl3	r0,#<fi2$s_filenamext+fi2$s_filename>,r0
	addl	r0,siz			;recalculate the size of the string
	movc3	r0,file_name,(r8)	;copy the file name to spec string

close_off_indexf:

	$qiow_s	chan=c,func=#io$_deaccess,-	;close the index file
		p1=fibd
	c_s
	cmpw	@12(ap),siz		;just return what he asks for
	blssu	string_too_long

	movl	12(ap),r8		;locate the string buffer
	movl	4(r8),r8
	movc3	siz,full_spec,(r8)	;return the full file spec
	movw	siz,@16(ap)		;return the size
	movl	#ss$_normal,r0		;wwe are history
	ret
EOF:	movl	#ss$_nosuchfile,r0
	brb	close_off_indexf
string_too_long:
	movzwl	@12(ap),r10		;reset length to original size
	movc3	r10,full_spec,(r8)
	movw	r10,@16(ap)
	movl	#ss$_normal,r0
	ret
	.end
