[comp.os.vms] code to set file protection

dorl@vms.macc.wisc.edu (Michael (NMI) Dorl) (06/27/87)

I am in need of some code to change a existing file's protection.
I've looked through the RMS manuals and found only the protection XAB.
The description of this XAB indicates that one can change a existing
files protection if you open it, write it (or otherwise update it),
and then close it with the XAB attached.  I can not make this work.
Even if I could, I might not want to modify the file.

The only other mechanism I can find for this purpose is the QIOW
IO$_Modify function.  This requires the whole directory and file
parsing route to get the file id.  I suppose one could use RMS for
this part of the task.  Is a FIB block and channel number hidden in
any of the RMS structures?

Am I missing something?  Seems there should be a better way to do
this.

Thanks,
Michael Dorl
dorl@vms.macc.wisc.edu
dorl@wiscmacc.bitnet

carl@CITHEX.CALTECH.EDU.UUCP (06/28/87)

 > I am in need of some code to  change  a  existing  file's  protection.   I've
 > looked  through  the  RMS  manuals  and  found  only the protection XAB.  The
 > description of this XAB indicates  that  one  can  change  a  existing  files
 > protection  if you open it, write it (or otherwise update it), and then close
 > it with the XAB attached.  I can not make this work.   Even  if  I  could,  I
 > might not want to modify the file.

The C program at the end of this answer will make it work.  You  don't  have  to
actually write or update the file; you must simply open it for PUT or UPD access
(my program uses the latter), and set the protection  to  something  other  than
what  it  used  to  be.   There is one hitch that I can't overcome, though:  RMS
apparently won't let you set the protection to (S:,O:,G:,W:); it thinks  of  the
value %XFFFF in the XAB$WPRO field as meaning "leave it the way it was".

 > The only other mechanism I can find for this purpose is  the  QIOW  IO$Modify
 > function.   This  requires  the whole directory and file parsing route to get
 > the file id.  I suppose one could use RMS for this part of the  task.   Is  a
 > FIB block and channel number hidden in any of the RMS structures?

The QIOW call might let you get around the problem I mentioned above.  The  easy
way  to  use  the  QIOW  is  is  to use RMS to get the file id.  To do this, you
specify a NAM block as well as the FAB block; then you $OPEN the file,  and  get
the FID out of NAM$WFID.

 > Am I missing something?  Seems there should be a better way to do this.

Well, you could, of course, use LIB$SPAWN to create a process to execute  a  DCL
"SET PROTECTION" command to change the protection :-(

carl@CITHEX.CALTECH.EDU (Carl J Lydick) (06/29/87)

Oops.  Somehow my earlier response managed to get away without the promised
code.  Here it is:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/* CHMOD -- SET	PROTECTION, UNIX style */
#define	RME$C_SETRFM 0X00000001
#include xab.h				  
#include <fab.h>
main(nargs, args)
int nargs;
char **args;
{	struct FAB myfab = cc$rms_fab;
	unsigned short mode;
	unsigned long status;
	struct XABPRO myxab = cc$rms_xabpro;
	if (--nargs < 2	|| sscanf(*++args,"%o%c", &mode, &status) != 1)
		exit((puts("USAGE: CHMOD mode file [file...]"),1));
/* Convert UNIX-style octal mode to VMS	protection mask	*/
/*	First, move unused,owner,group,world to world,group,owner,system 
		using owner protection for system as well */
	mode = (((mode & 0007) << 12) |	((mode & 0070) << 5) |
		((mode & 0700) >> 2)  |	((mode & 0700) >> 6));
/*	Then move unused,read,write,execute to delete,execute,write,read
		using write access for delete	as well, then complement */
	mode = ~(((mode	& 0x1111) << 2)	| ((mode & 0x2222)) | 
		 ((mode	& 0x2222) << 2)	| ((mode & 0x4444) >> 2));
/* Initialize fab block	*/
	myfab.fab$l_xab	= &myxab;
	myfab.fab$b_fac	= FAB$M_UPD;
	myfab.fab$l_fop	|= FAB$M_ESC;
	myfab.fab$l_ctx	|= RME$C_SETRFM;
	myfab.fab$w_ifi	= 0;
	while (--nargs > 0) {
/* Set up fab for next file */
		myfab.fab$l_fna	= *++args;
		myfab.fab$b_fns	= strlen(*args);
/* Open	the file */
		if (((status = SYS$OPEN(&myfab,	0, 0)) & 7) != 1)
			exit((printf("Couldn't open %s\n", *args), status));
/* Set the protection field in the XAB */
		myxab.xab$w_pro	= mode;
/* Update the file header */
		if (((status = SYS$MODIFY(&myfab, 0, 0)) & 7) != 1)
			exit((printf("Couldn't modify %s\n", *args), status));
/* Close the file */
		if (((status = SYS$CLOSE(&myfab, 0, 0))	& 7) !=	1)
			exit((printf("Couldn't close %s\n", *args), status));
	}
}