From: Hein van den Heuvel [hein_netscape@eps.zko.dec.com] Sent: Wednesday, December 03, 2003 4:26 PM To: Info-VAX@Mvb.Saic.Com Subject: Re: How do you modify RMS file attributes when using ofstream I/O ? Stuart wrote: > cheers guys, > > We've sorted it now. Used lib$spawn to carry out 'set file/attributes' > commands on the files after they have been created. Great. No problem if you do it once an hour and have the resources. If spawning is too expensive / difficult / slow, then you may want to consider a subroutine. Now SET FILE is not callable. There are 3 ways to code this up, and I will provide examples for each as they are all tricky. 1) The more or less documented ACP QIO to change RECATTR in the file header. 2) A simple RMS 'trick' with normal calls for sequential files only. Easy enough. 3) Using the undocumented RMS SYS$MODIFY call. > The problem came around because a fortran application used to view the > files(created in C++ using ofstream) was allocating memory for a line length > buffer to that of the rms file attribute 'longest line bytes', which was set > to 0 therefore not reading anything out of the file. You may want to check out the usage of the logical name DECC$DEFAULT_LRL Eamples below.... [hey... it's almost Xmass time ;-) ] Hein. U$1:[HEIN.EXAMPLES]LRL_MODIFY.C;1 /* ** lrl_modify.c Hein van den Heuvel, December 2003 ** ** Template program to set RMS LRL attributes for RMS files. ** This is done as a side effect of temporarely changing the file ** attributes in memory to fixed-length through sys$modify. ** Usage: Define as external DCL command and pass filespec as param. ** Have fun. */ #include #include #include #include int set_lrl (char *filename, int lrl) { struct FAB fab; struct XABFHC fhc; size_t strlen(); int stat, rfm, mrs, sys$open(), sys$close(), sys$modify(); fab = cc$rms_fab; fhc = cc$rms_xabfhc; fab.fab$b_fac = FAB$M_PUT | FAB$M_TRN; fab.fab$l_fna = filename; fab.fab$b_fns = strlen( filename ); fab.fab$l_xab = (void *) &fhc; stat = sys$open ( &fab ); if (!(stat&1)) return stat; if (lrl > 32767) return RMS$_RSZ; mrs = fab.fab$w_mrs; rfm = fab.fab$b_rfm; fab.fab$l_ctx = RME$C_SETRFM; fab.fab$v_esc = 1; fab.fab$w_mrs = lrl; fab.fab$b_rfm = FAB$C_FIX; stat = sys$modify ( &fab ); if (stat & 1) { fab.fab$w_mrs = mrs; fab.fab$b_rfm = rfm; stat = sys$modify ( &fab ); } if (stat&1) stat = sys$close(&fab); return stat; } main (int argc, char *argv[]) { if (argc < 3) { printf ("Usage: %s \n", argv[0]); return 1; } return set_lrl ( argv[1], atoi(argv[2]) ); } U$1:[HEIN.EXAMPLES]LRL_QIO.C;1 /* ** lrl_qio.c Hein van den Heuvel, December 2003 ** ** Template program to set RMS LRL attribute for RMS files. ** This is done using an ACP QIO. ** Usage: Define as external DCL command and pass filespec as param. ** Have fun. */ #include #include atrdef #include fibdef /* fdhdef and fatdef live in lib.mlb and SYS$LIB_C.TLB */ #include iodef #include stdio #include stdlib #include string #define FAT$W_RSIZE 1 int set_lrl (char *filename, int lrl) { struct fibdef fib; size_t strlen(); int stat, channel, sys$open(), sys$close(), sys$qiow(); union { char fill[ATR$S_RECATTR]; short word[5];}fat; /* fake it, as fat.h not always present */ short iosb[4]; struct { long count; void *address; } fibdes; struct atrdef atr[2]; struct FAB fab; struct NAM nam; fab = cc$rms_fab; nam = cc$rms_nam; fab.fab$b_fac = FAB$M_PUT | FAB$M_TRN; fab.fab$l_fna = filename; fab.fab$b_fns = strlen( filename ); fab.fab$b_fac = FAB$M_GET | FAB$M_PUT; fab.fab$l_fop = FAB$M_UFO; fab.fab$l_nam = &nam; fab.fab$l_fna = filename; fab.fab$b_fns = strlen( filename ); memset (&fib, 0, sizeof(fib)); if (lrl > 32767) return RMS$_RSZ; stat = sys$open ( &fab ); if (!(stat&1)) return stat; channel = fab.fab$l_stv; fibdes.count = sizeof(fib); fibdes.address = &fib; fib.fib$l_acctl = ( FIB$M_WRITE ); fib.fib$w_fid_num = nam.nam$w_fid[0]; fib.fib$w_fid_seq = nam.nam$w_fid[1]; fib.fib$w_fid_rvn = nam.nam$w_fid[2]; /* ** Need to get record attributes first to set new rsize */ atr[0].atr$w_type = ATR$C_RECATTR; atr[0].atr$w_size = ATR$S_RECATTR; atr[0].atr$l_addr = &fat; atr[1].atr$w_type = 0; atr[1].atr$w_size = 0; /* Get the file's current attributes */ stat = sys$qiow(0,channel,IO$_ACCESS,iosb,0,0,&fibdes,0,0,0,&atr,0); if (stat & 1) stat = iosb[0]; if (!(stat & 1)) return stat; fat.word[FAT$W_RSIZE] = lrl; /* $FATDEF in LIB.MLB */ stat = sys$qiow(0,channel,IO$_MODIFY,iosb,0,0,&fibdes,0,0,0,&atr,0); if (stat & 1) stat = iosb[0]; if (!(stat & 1)) return stat; return sys$qiow(0,channel,IO$_DEACCESS,iosb,0,0,&fibdes,0,0,0,0,0); } main (int argc, char *argv[]) { if (argc < 3) { printf ("Usage: %s \n", argv[0]); return 1; } return set_lrl ( argv[1], atoi(argv[2]) ); } U$1:[HEIN.EXAMPLES]LRL_TRUNCATE.C;1 /* ** lrl_truncate.c Hein van den Heuvel, December 2003 ** ** Template program to incease RMS LRL attribute for sequential files. ** This is done by temporarely appending a record with size LRL and ** truncating the file at the insertion point to remove that record. ** Usage: Define as external DCL command and pass filespec as param. ** Have fun. */ #include #include #include int set_lrl (char *filename, int lrl) { struct FAB fab; struct RAB rab; struct XABFHC fhc; size_t strlen(); int stat, sys$display(), sys$open(), sys$close(), sys$put(), sys$connect(), sys$truncate(); fab = cc$rms_fab; rab = cc$rms_rab; fhc = cc$rms_xabfhc; fab.fab$b_fac = FAB$M_PUT | FAB$M_TRN; fab.fab$l_fna = filename; fab.fab$b_fns = strlen( filename ); fab.fab$l_xab = (void *) &fhc; rab.rab$l_fab = &fab; rab.rab$l_rbf = (void *) malloc ( lrl ); /* sys$put will test for succes */ rab.rab$w_rsz = lrl; rab.rab$l_rop = RAB$M_EOF; stat = sys$open ( &fab ); if (!(stat&1)) return stat; if (fab.fab$b_org!=FAB$C_SEQ) return RMS$_ORG; if (fhc.xab$w_lrl > lrl || lrl > 32767) return RMS$_RSZ; stat = sys$connect (&rab); /* sys$put will test for succes */ stat = sys$put (&rab); /* append record with length LRL, giving RFA */ if (!(stat&1)) return stat; /* returns RMS$_RBF if malloc failed */ free ( rab.rab$l_rbf ); rab.rab$b_rac = RAB$C_RFA; stat = sys$truncate (&rab); /* remove that helper record */ if (stat&1) stat = sys$close(&fab); return stat; } main (int argc, char *argv[]) { if (argc < 3) { printf ("Usage: %s \n", argv[0]); return 1; } return set_lrl ( argv[1], atoi(argv[2]) ); }