From:	CSBVAX::MRGATE!COSC1Q0@uhvax1.uh.edu@SMTP 25-APR-1988 15:43
To:	ARISIA::EVERHART
Subj:	File attribute meddling


Received: from uhvax1.uh.edu by KL.SRI.COM with TCP; Tue 19 Apr 88 21:36:08-PDT
Date: Tue, 19 Apr 88 23:35 CST
From: "Lee K. Gleason, Control-G Consultants" <COSC1Q0@uhvax1.uh.edu>
Subject: File attribute meddling
To: INFO-VAX@KL.SRI.com
X-VMS-To: IN%"INFO-VAX@KL.SRI.COM",COSC1Q0

Jeff Capehart <ukma!uflorida!beach.cis.ufl.edu!jdc@NRL-CMF.ARPA> asks...
     
>I have been wondering if it is possible (without privs, but with ownership)
>to change the attributes of a file.  Now, please do not misunderstand.  I
>am very well aware that FDL can be used to edit it to whatever and then
>use the convert/fdl.  However, *MY* question is, can you change the
>attributes of an existing file?   The CONVERT will create a *NEW* file
>with the *NEW* characteristics/attributes.  Any attempt to COPY/OVERLAY
>will fail because of incompatible attributes.  I cannot really think
>of any specific example, or why I had wanted to do this.  Perhaps it
>was a disk quota limitation or some such thing.  Anyways, I am just
>curious if it is at all possible.  I figure it will require some calls
>to the QIO-ACP routines, but I don't have easy access to that manual.
     

  Well, if by change the attributes, you mean use ACP QIOs to
change things in the file header, the answer is yes. Following
is a little utility, ICONV, that does just that, along with a help file.
  If, however, you mean to effect a REAL change in the file format
(ie, convert fixed records into variable length ones, with byte
counts and trailing nulls, and all, then the answer is no.

  To use ICONV...cut this overly long message up into ICONV.MAR
and ICONV.HLP. Then...

$ MAC ICONV
$ LINK ICONV
$ LIBR/CREATE/HELP ICONV.HLB ICONV.HLP
$ DEF ICONVDIR somedisk:[somedir]  !define a logical for the help library
$ COPY ICONV.HLP ICONVDIR:	   !and, put it there
Then, you can

$ RUN ICONV

and be prompted, or define it as a foreign command

$ ICONV:==somedisk:[somedir]ICONV

and use it with complete command lines.

  ICONV will accept wild card file specs. It will print the name of
each file as it is processed. There is a better file attribute
changing program (I don't recall who wrote it) on one of the DECUS
tapes, but it's in VAX BASIC (an excellent language, actually, 
but not available at most VAX sites).

Lee K. Gleason			Disclaimer:
Control-G Consultants		    "No, Officer, no one here by that name."
2416 Branard #D
Houston TX 77098
Phone 713/528-1859
COSC1Q0@UHVAX1.UH.EDU (but, not after May 2nd).

	"Oh well a Touch of Grey, kind of suits me, anyway."


****************************************************************
		CUT HERE!!!!
		Following file is ICONV.MAR
****************************************************************
	.title	ICONV
	.ident	/X01-001/

	.library	"sys$library:lib.mlb"

	$fibdef		;define fib block offsets
	$atrdef		;attributes
	$fchdef		;more attributes
	$fatdef		;yet still more attributes
	$tpadef		;tparse definitions
	$qiodef		;qio offsets
	$hlpdef

swi$m_type    = 1
swi$m_org     = 2
swi$m_cc      = 4
swi$m_rsize   = 8
swi$m_vfcsize = 16
swi$m_maxrec  = 32
swi$m_nospan  = 64
swi$m_credate = 128
swi$m_revdate = 256
swi$m_expdate = 512
swi$m_bakdate = 1024
swi$v_type    = 0
swi$v_org     = 1
swi$v_cc      = 2
swi$v_rsize   = 3
swi$v_vfcsize = 4
swi$v_maxrec  = 5
swi$v_nospan  = 6
swi$v_credate = 7
swi$v_revdate = 8
swi$v_expdate = 9
swi$v_bakdate = 10

	.psect	icopur pic,long,usr,con,rel,gbl,shr,noexe,rd,nowrt,novec

hlib:	.ascid	/iconvdir:iconv.hlb/
helpline:
	.ascid	/ICONV/

hflags:	.long	hlp$m_prompt!hlp$m_help

inprompt:
	.ascid	/Yes?...>/	;silly prompt


	.psect	icodat pic,long,usr,con,rel,gbl,noshr,noexe,rd,wrt,novec

type_byte:	.long	0
org_byte:	.long	0
cc_byte:	.long	0
nospan_byte:	.long	0
rsize:		.long	0
vfcsize:	.long	0
maxrec:		.long	0
switch:		.long	0

credate:	.quad	0
revdate:	.quad	0
expdate:	.quad	0
bakdate:	.quad	0

tparse_block:			;argument block for call to LIB$TPARSE
	.long	tpa$k_count0
	.long
	.blkb	tpa$k_length0-8

	$init_state	tparse_key_state,tparse_key_key

	$state	mod_state
	$tran	!help_state,tpa$_exit, ,1,norun
	$tran	!type_state,mod_state
	$tran	!org_state,mod_state
	$tran	!cc_state,mod_state
	$tran	!rsize_state,mod_state
	$tran	!maxrec_state,mod_state
	$tran	!vfc_state,mod_state
	$tran	!span_state,mod_state
	$tran	!credate_state,mod_state
	$tran	!revdate_state,mod_state
	$tran	!expdate_state,mod_state
	$tran	!bakdate_state,mod_state
	$tran	tpa$_eos,tpa$_exit			;end of command
	$tran	tpa$_filespec,mod_state,nonulfil , ,fildesc	;filespec


	$state	help_state
	$tran	'HELP'
	$state
	$tran	tpa$_string,tpa$_exit,helpem
	$tran	tpa$_eos,tpa$_exit,helpem

	$state	type_state
	$tran	'/'
	$state
	$tran	'TYPE'
	$state
	$tran	!sep
	$state
	$tran	'FIXED', , ,fat$c_fixed,type_byte
	$tran	'VARIABLE', , ,fat$c_variable,type_byte
	$tran	'VFC', , ,fat$c_vfc,type_byte
	$tran	'UNDEFINED', , ,fat$c_undefined,type_byte
	$tran	'STREAM', , ,fat$c_stream,type_byte
	$tran	'STREAMCR', , ,fat$c_streamcr,type_byte
	$tran	'STREAMLF', , ,fat$c_streamlf,type_byte
	$state
	$tran	tpa$_lambda,tpa$_exit, ,swi$m_type,switch

	$state	org_state
	$tran	'/'
	$state
	$tran	'ORG'
	$state
	$tran	!sep
	$state
	$tran	'DIRECT', , ,fat$c_direct,org_byte
	$tran	'INDEXED', , ,fat$c_indexed,org_byte
	$tran	'RELATIVE', , ,fat$c_relative,org_byte
	$tran	'SEQUENTIAL', , ,fat$c_sequential,org_byte
	$state
	$tran	tpa$_lambda,mod_state, ,swi$m_org,switch

	$state	cc_state
	$tran	'/'
	$state
	$tran	'CC'
	$state
	$tran	!sep
	$state
	$tran	'FORTRAN', , ,fat$m_fortrancc,cc_byte
	$tran	'IMPLIED', , ,fat$m_impliedcc,cc_byte
	$tran	'PRINT', , ,fat$m_printcc,cc_byte
	$tran	'NONE', , ,0,cc_byte
	$state
	$tran	tpa$_lambda,mod_state, ,swi$m_cc,switch

	$state	span_state
	$tran	'/'
	$state
	$tran	'NOSPAN', ,nospan_routine
	$tran	'SPAN', ,span_routine
	$state
	$tran	tpa$_lambda,mod_state, ,swi$m_nospan,switch

	$state	rsize_state
	$tran	'/'
	$state
	$tran	'RSIZE'
	$state
	$tran	!sep
	$state
	$tran	tpa$_decimal, , , ,rsize
	$state
	$tran	tpa$_lambda,mod_state, ,swi$m_rsize,switch

	$state	vfc_state
	$tran	'/'
	$state
	$tran	'VFCSIZE'
	$state
	$tran	!sep
	$state
	$tran	tpa$_decimal, , , ,vfcsize
	$state
	$tran	tpa$_lambda,mod_state, ,swi$m_vfcsize,switch

	$state	maxrec_state
	$tran	'/'
	$state
	$tran	'MAXREC'
	$state
	$tran	!sep
	$state
	$tran	tpa$_decimal, , , ,maxrec
	$state
	$tran	tpa$_lambda,mod_state, ,swi$m_maxrec,switch

	$state	credate_state
	$tran	'/'
	$state
	$tran	'CREDATE'
	$state
	$tran	!sep
	$state
	$tran	tpa$_string, ,check_date, , ,credate
	$state
	$tran	tpa$_lambda,mod_state, ,swi$m_credate,switch

	$state	revdate_state
	$tran	'/'
	$state
	$tran	'REVDATE'
	$state
	$tran	!sep
	$state
	$tran	tpa$_string, ,check_date, , ,revdate
	$state
	$tran	tpa$_lambda,mod_state, ,swi$m_revdate,switch

	$state	bakdate_state
	$tran	'/'
	$state
	$tran	'BAKDATE'
	$state
	$tran	!sep
	$state
	$tran	tpa$_string, ,check_date, , ,bakdate
	$state
	$tran	tpa$_lambda,mod_state, ,swi$m_bakdate,switch

	$state	expdate_state
	$tran	'/'
	$state
	$tran	'EXPDATE'
	$state
	$tran	!sep
	$state
	$tran	tpa$_string, ,check_date, , ,expdate
	$state
	$tran	tpa$_lambda,mod_state, ,swi$m_expdate,switch

	$state	sep		;subexpression for valid separators
	$tran	'=',tpa$_exit
	$tran	':',tpa$_exit
	$end_state

indesc:	.long	255		;place to store command line
	.address	.+4
	.blkb	255
inlen:	.long	0		;place to return input length


fibdesc:		;fib block descriptor
fiblen:	.long	100		
	.address	fibblk
fibblk:	.blkb	100

attlst:				;fib request list
	.word	atr$s_recattr	;record attributes
	.word	atr$c_recattr
	.address	recattbuf
	.long	0

recattbuf:
	.blkb	40

q1blk:	$qiow	func = io$_access,-	;read file attributes function
		iosb = iosb,-		;let's use an iosb
		chan = chan,-		;dummy chan parameter
		p1   = fibdesc,-	;file information block
		p5   = attlst		;attribute request block

q2blk:	$qiow	func = io$_modify,-	;read file attributes function
		iosb = iosb,-		;let's use an iosb
		chan = chan,-		;dummy chan parameter
		p1   = fibdesc,-	;file information block
		p5   = attlst		;attribute request block

topdesc:			;descriptor for top level directory
toplen:	.long	128
topadr:	.address	.+4
topbuf:	.blkb	128
	.align	long		

topfab:	$fab	nam=topnam			;we'll need a fab
topnam:	$nam	esa = topexpbuf,-	;place for expanded file name
		ess = nam$c_maxrss,-	;and it's length
		rsa = topresbuf,-	;place for resultant file name
		rss = nam$c_maxrss	;and it's length
devdesc:			;descriptor for device name
devlen:	.long	0
devadr:	.long	0

norun:	.long	0

topresdesc:	.long	nam$c_maxrss	;rsa
		.address	topresbuf
topresbuf:	.blkb	nam$c_maxrss
topexpdesc:	.long	nam$c_maxrss	;esa
		.address	topexpbuf
topexpbuf:	.blkb	nam$c_maxrss

fildesc:
	.long	80
	.address	.+4
	.blkb	80

outstr:	.long	80				;palce for output
	.address .+4
	.blkb	80

chan:	.long	0
iosb:	.quad	0



	.psect	icocod pic,long,usr,con,rel,gbl,shr,exe,rd,nowrt,novec

	.entry	iconv,^m<>

	pushal	inlen			;place to store command line length
	clrl	-(sp)			;no prompt first time
	pushal	indesc			;place to store command line
	calls	#3,g^lib$get_foreign	;try for a command line
	blbc	r0,out			;if error, we gotta die
	tstl	inlen			;is it a null line?
	bgtr	proceed			;nope, we got a real one
	pushal	inlen			;let's try again...
	pushal	inprompt		;...with a prompt this time
	pushal	indesc			;same place
	calls	#3,g^lib$get_foreign	;here goes...
	blbc	r0,out			;if trouble, then get out
	tstl	inlen			;anything really there?
	bgtr	proceed			;yup, so let's proceed


out:	cmpl	#^X182CA,r0
	bneq	1$
	movl	#1,r0
1$:	$exit_s	r0			;let's get outa here

again:	clrl	norun
	clrl	inlen
	pushal	inlen			;let's try again...
	pushal	inprompt		;...with a prompt this time
	pushal	indesc			;same place
	calls	#3,g^lib$get_input	;here goes...
	blbc	r0,out
	tstl	inlen
	bleq	out
	

proceed:
	movzwl	inlen,tparse_block+tpa$l_stringcnt    ;length of command string
	movl	indesc+4,tparse_block+tpa$l_stringptr ;addr of command string
	pushal	tparse_key_key			;push keyword table address
	pushal	tparse_key_state		;push state table address
	pushal	tparse_block			;push tparse arg block address
	calls	#3,g^lib$tparse			;parse commnad line
	blbc	r0,out				;and it better be good...
	blbc	norun,1$
	brw	again
1$:

	movl	#fib$m_writethru,fib$l_acctl+fibblk	;update headers as we go

	bisw	#fib$m_findfid,fib$w_nmctl+fibblk		;find by fid

rnext:	$fab_store	fab = topfab,-
			fns = fildesc,-
			fna = @fildesc+4	;put current name in fab
	$parse	fab = topfab				;parse it
	blbs	r0,next
	brw	nuts

next:	$search	fab = topfab			;find it
	blbs	r0,1$
	brw	out
1$:	pushal	topresdesc
	calls	#1,g^lib$put_output

	moval	topnam,r11
	movzbl	nam$t_dvi(r11),devlen		;len of dev name to descriptor
	moval	nam$t_dvi+1(r11),devadr	;addr of dev name to descriptor
	movl	nam$w_did(r11),fibblk+fib$w_did
	movw	nam$w_did+4(r11),fibblk+fib$w_did+4
	movl	nam$w_fid(r11),fibblk+fib$w_fid
	movw	nam$w_fid+4(r11),fibblk+fib$w_fid+4

	$assign_s -			;assign output device channel
		chan = chan, -		;this channel
		devnam = devdesc	;this device

	movl	chan,qio$_chan+q1blk	;store chan in qioblk
	movl	chan,qio$_chan+q2blk	;store chan in qioblk

	$qiow_g	q1blk		;do the set
	blbs	r0,2$		;ok?
	brw	nuts

2$:	movl	iosb,r0
	blbs	r0,3$		;really ok?
	brw	nuts

3$:	moval	recattbuf,r11
	bbc	#swi$v_type,switch,10$
	bicb	#^X0F,fat$b_rtype(r11)
	bisb	type_byte,fat$b_rtype(r11)

10$:	bbc	#swi$v_org,switch,20$
	bicb	#^XF0,fat$b_rtype(r11)
	mull3	org_byte,#16,r0
	bisb	r0,fat$b_rtype(r11)

20$:	bbc	#swi$v_cc,switch,30$
	movb	cc_byte,fat$b_rattrib(r11)
30$:	bbc	#swi$v_rsize,switch,40$
	movw	rsize,fat$w_rsize(r11)
40$:	bbc	#swi$v_maxrec,switch,50$
	movw	maxrec,fat$w_maxrec(r11)
50$:	bbc	#swi$v_vfcsize,switch,60$
	movw	vfcsize,fat$b_vfcsize(r11)
		
60$:	bbc	#swi$v_nospan,switch,70$	;was there a span?
	insv	nospan_byte,#fat$v_nospan,#1,fat$b_rattrib(r11)
70$:	$qiow_g	q2blk		;do the set
	blbc	r0,nuts		;ok?
	blbc	iosb,nuts	;really ok?
	$dassgn_s	chan = chan
	brw	next
nuts:	cmpl	#^X182CA,r0
	bneq	1$
	movl	#1,r0
1$:	$exit_s

	.entry	span_routine,^m<>
	bicb	#1,nospan_byte
	ret

	.entry	nospan_routine,^m<>
	bisb	#1,nospan_byte
	ret

	.entry	check_date,^m<>
	pushl	tpa$l_param(ap)
	pushal	tpa$l_tokencnt(ap)
	calls	#2,sys$bintim	
	blbs	r0,1$
	$exit_s	r0
1$:	ret

	.entry	nonulfil,^m<>
	tstl	tpa$l_tokencnt(ap)
	bneq	1$
	clrl	r0
1$:	ret

	.entry	helpem,^m<>

	pushal	g^lib$get_input
	pushal	hflags
	pushal	hlib
	pushal	helpline
	pushal	#0
	pushal	g^lib$put_output
	calls	#6,g^lbr$output_help
	ret

	.end	iconv


*********************************************************************
			CUT HERE!!!
			File following is ICONV.HLP
*********************************************************************
1 ICONV
  This is ICONV, a program for changing the attributes of a file,
  brought to you by those friendly folks at Control-G Consultants.
  Use at your own risk - this is serious business.

  Format:


    ICONV input-file-spec

2 Parameters

 input-file-spec

  Specifies the name of input file(s) to be mangled.
  You can use wildcard characters in the input file specifications.

2 Command_Qualifiers

/TYPE
 /TYPE=[option]

  This qualifier is used to change the TYPE attribute of the file.
  Valid TYPES are...

	FIXED
	VARIABLE
	VFC
	UNDEFINED
	STREAM
	STREAMCR
	STREAMLF

/ORG
 /ORG = [option]

  This qualifier is used to change the file organization.
  Valid options are...

	DIRECT
	INDEXED
	RELATIVE
	SEQUENTIAL
  
/CC
 /CC = [option]

  This qualifier is used to change the Carriage Control attribute
  of the file. Valid options are...

	FORTRAN
	IMPLIED
	PRINT
	NONE

/SPAN
 /SPAN = [option]

  This qualifier is used to change the block spanning attribute.
  Valid options are...

	NOSPAN
	SPAN

/RSIZE
 /RSIZE = [value]

  This qualifier is used to set the record size of the file.
  Don't make it too big, or too small, ok?

/VFCSIZE
 /VFCSIZE = [value]

  This qualifier is used to set the size of the VFC control field.
  It would be a good idea to set CC to VFC if you plan to use
  this qualifier, nicht wahr?

/MAXREC
 /MAXREC = [value]

  This qualifer is used to set the size of the maximum allowable
  record in the file.

/CREDATE
 /CREDATE = [date-time]

  This qualifer would reset the creation date of the file, if it
  worked, which it doesn't, since VAX date and time are a bitch
  to parse. It'll be in Version 2, ok?

/BAKDATE
 /BAKDATE = [date-time]

  This qualifer would reset the creation date of the file, if it
  worked, which it doesn't, since VAX date and time are a bitch
  to parse.  It'll be in Version 2, ok?


/REVDATE
 /REVDATE = [date-time]

  This qualifer would reset the revision date of the file, if it
  worked, which it doesn't, since VAX date and time are a bitch
  to parse.  It'll be in Version 2, ok?

/EXPDATE
 /EXPDATE = [date-time]

  This qualifer would reset the expiration date of the file, if it
  worked, which it doesn't, since VAX date and time are a bitch
  to parse.  It'll be in Version 2, ok?

*********************************************************************
		END OF FILES
*********************************************************************

