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)); } }