1*50bf276cStholo /*---------------------------------------------------------------------------
2*50bf276cStholo
3*50bf276cStholo VMSmunch.c version 1.3 28 Apr 1992
4*50bf276cStholo
5*50bf276cStholo This routine is a blatant and unrepentent appropriation of all the nasty
6*50bf276cStholo and difficult-to-do and complicated VMS shenanigans which Joe Meadows has
7*50bf276cStholo so magnificently captured in his FILE utility. Not only that, it's even
8*50bf276cStholo allowed! (see below). But let it be clear at the outset that Joe did all
9*50bf276cStholo the work; yea, verily, he is truly a godlike unit.
10*50bf276cStholo
11*50bf276cStholo The appropriations and modifications herein were performed primarily by
12*50bf276cStholo him known as "Cave Newt," although the Info-ZIP working group probably had
13*50bf276cStholo their fingers in it somewhere along the line. The idea is to put the raw
14*50bf276cStholo power of Joe's original routine at the disposal of various routines used
15*50bf276cStholo by UnZip (and Zip, possibly), not least among them the utime() function.
16*50bf276cStholo Read on for details...
17*50bf276cStholo
18*50bf276cStholo 18-JUL-1994 Hunter Goatley <goathunter@WKU.EDU>
19*50bf276cStholo Fixed IO$_ACCESS call.
20*50bf276cStholo
21*50bf276cStholo 18-Jul-1994 Richard Levitte levitte@e.kth.se
22*50bf276cStholo Changed VMSmunch() to deassign the channel before
23*50bf276cStholo returning when an error has occured.
24*50bf276cStholo
25*50bf276cStholo 02-Apr-1994 Jamie Hanrahan jeh@cmkrnl.com
26*50bf276cStholo Moved definition of VMStimbuf struct from here
27*50bf276cStholo to vmsmunch.h
28*50bf276cStholo ---------------------------------------------------------------------------
29*50bf276cStholo
30*50bf276cStholo Usage (i.e., "interface," in geek-speak):
31*50bf276cStholo
32*50bf276cStholo int VMSmunch( char *filename, int action, char *ptr );
33*50bf276cStholo
34*50bf276cStholo filename the name of the file on which to be operated, obviously
35*50bf276cStholo action an integer which specifies what action to take
36*50bf276cStholo ptr pointer to any extra item which may be needed (else NULL)
37*50bf276cStholo
38*50bf276cStholo The possible values for the action argument are as follows:
39*50bf276cStholo
40*50bf276cStholo GET_TIMES get the creation and revision dates of filename; ptr
41*50bf276cStholo must point to an empty VMStimbuf struct, as defined
42*50bf276cStholo in vmsmunch.h
43*50bf276cStholo (with room for at least 24 characters, including term.)
44*50bf276cStholo SET_TIMES set the creation and revision dates of filename (utime
45*50bf276cStholo option); ptr must point to a valid VMStimbuf struct,
46*50bf276cStholo as defined in vmsmunch.h
47*50bf276cStholo GET_RTYPE get the record type of filename; ptr must point to an
48*50bf276cStholo integer which, on return, is set to the type (as defined
49*50bf276cStholo in VMSmunch.h: FAT$C_* defines)
50*50bf276cStholo CHANGE_RTYPE change the record type to that specified by the integer
51*50bf276cStholo to which ptr points; save the old record type (later
52*50bf276cStholo saves overwrite earlier ones)
53*50bf276cStholo RESTORE_RTYPE restore the record type to the previously saved value;
54*50bf276cStholo or, if none, set it to "fixed-length, 512-byte" record
55*50bf276cStholo format (ptr not used)
56*50bf276cStholo
57*50bf276cStholo ---------------------------------------------------------------------------
58*50bf276cStholo
59*50bf276cStholo Comments from FILE.C, a utility to modify file characteristics:
60*50bf276cStholo
61*50bf276cStholo Written by Joe Meadows Jr, at the Fred Hutchinson Cancer Research Center
62*50bf276cStholo BITNET: JOE@FHCRCVAX
63*50bf276cStholo PHONE: (206) 467-4970
64*50bf276cStholo
65*50bf276cStholo There are no restrictions on this code, you may sell it, include it
66*50bf276cStholo with any commercial package, or feed it to a whale.. However, I would
67*50bf276cStholo appreciate it if you kept this comment in the source code so that anyone
68*50bf276cStholo receiving this code knows who to contact in case of problems. Note that
69*50bf276cStholo I do not demand this condition..
70*50bf276cStholo
71*50bf276cStholo ---------------------------------------------------------------------------*/
72*50bf276cStholo
73*50bf276cStholo
74*50bf276cStholo
75*50bf276cStholo
76*50bf276cStholo /*****************************/
77*50bf276cStholo /* Includes, Defines, etc. */
78*50bf276cStholo /*****************************/
79*50bf276cStholo
80*50bf276cStholo #include <descrip.h>
81*50bf276cStholo #include <rms.h>
82*50bf276cStholo #include <stdio.h>
83*50bf276cStholo #include <iodef.h>
84*50bf276cStholo #include <string.h>
85*50bf276cStholo #include <starlet.h>
86*50bf276cStholo #include <atrdef.h> /* this gets created with the c3.0 compiler */
87*50bf276cStholo #include <fibdef.h> /* this gets created with the c3.0 compiler */
88*50bf276cStholo
89*50bf276cStholo #include "VMSmunch.h" /* GET/SET_TIMES, RTYPE, etc. */
90*50bf276cStholo #include "VMSmunch_private.h" /* fatdef.h, etc. */
91*50bf276cStholo
92*50bf276cStholo #define RTYPE fat$r_rtype_overlay.fat$r_rtype_bits
93*50bf276cStholo #define RATTRIB fat$r_rattrib_overlay.fat$r_rattrib_bits
94*50bf276cStholo
95*50bf276cStholo static void asctim();
96*50bf276cStholo static void bintim();
97*50bf276cStholo
98*50bf276cStholo /* from <ssdef.h> */
99*50bf276cStholo #ifndef SS$_NORMAL
100*50bf276cStholo # define SS$_NORMAL 1
101*50bf276cStholo # define SS$_BADPARAM 20
102*50bf276cStholo #endif
103*50bf276cStholo
104*50bf276cStholo
105*50bf276cStholo
106*50bf276cStholo
107*50bf276cStholo
108*50bf276cStholo /*************************/
109*50bf276cStholo /* Function VMSmunch() */
110*50bf276cStholo /*************************/
111*50bf276cStholo
VMSmunch(filename,action,ptr)112*50bf276cStholo int VMSmunch( filename, action, ptr )
113*50bf276cStholo char *filename, *ptr;
114*50bf276cStholo int action;
115*50bf276cStholo {
116*50bf276cStholo
117*50bf276cStholo /* original file.c variables */
118*50bf276cStholo
119*50bf276cStholo static struct FAB Fab;
120*50bf276cStholo static struct NAM Nam;
121*50bf276cStholo static struct fibdef Fib; /* short fib */
122*50bf276cStholo
123*50bf276cStholo static struct dsc$descriptor FibDesc =
124*50bf276cStholo {sizeof(Fib),DSC$K_DTYPE_Z,DSC$K_CLASS_S,(char *)&Fib};
125*50bf276cStholo static struct dsc$descriptor_s DevDesc =
126*50bf276cStholo {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,&Nam.nam$t_dvi[1]};
127*50bf276cStholo static struct fatdef Fat;
128*50bf276cStholo static union {
129*50bf276cStholo struct fchdef fch;
130*50bf276cStholo long int dummy;
131*50bf276cStholo } uchar;
132*50bf276cStholo static struct fjndef jnl;
133*50bf276cStholo static long int Cdate[2],Rdate[2],Edate[2],Bdate[2];
134*50bf276cStholo static short int revisions;
135*50bf276cStholo static unsigned long uic;
136*50bf276cStholo static union {
137*50bf276cStholo unsigned short int value;
138*50bf276cStholo struct {
139*50bf276cStholo unsigned system : 4;
140*50bf276cStholo unsigned owner : 4;
141*50bf276cStholo unsigned group : 4;
142*50bf276cStholo unsigned world : 4;
143*50bf276cStholo } bits;
144*50bf276cStholo } prot;
145*50bf276cStholo
146*50bf276cStholo static struct atrdef Atr[] = {
147*50bf276cStholo {ATR$S_RECATTR,ATR$C_RECATTR,&Fat}, /* record attributes */
148*50bf276cStholo {ATR$S_UCHAR,ATR$C_UCHAR,&uchar}, /* File characteristics */
149*50bf276cStholo {ATR$S_CREDATE,ATR$C_CREDATE,&Cdate[0]}, /* Creation date */
150*50bf276cStholo {ATR$S_REVDATE,ATR$C_REVDATE,&Rdate[0]}, /* Revision date */
151*50bf276cStholo {ATR$S_EXPDATE,ATR$C_EXPDATE,&Edate[0]}, /* Expiration date */
152*50bf276cStholo {ATR$S_BAKDATE,ATR$C_BAKDATE,&Bdate[0]}, /* Backup date */
153*50bf276cStholo {ATR$S_ASCDATES,ATR$C_ASCDATES,&revisions}, /* number of revisions */
154*50bf276cStholo {ATR$S_FPRO,ATR$C_FPRO,&prot}, /* file protection */
155*50bf276cStholo {ATR$S_UIC,ATR$C_UIC,&uic}, /* file owner */
156*50bf276cStholo {ATR$S_JOURNAL,ATR$C_JOURNAL,&jnl}, /* journal flags */
157*50bf276cStholo {0,0,0}
158*50bf276cStholo } ;
159*50bf276cStholo
160*50bf276cStholo static char EName[NAM$C_MAXRSS];
161*50bf276cStholo static char RName[NAM$C_MAXRSS];
162*50bf276cStholo static struct dsc$descriptor_s FileName =
163*50bf276cStholo {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
164*50bf276cStholo static struct dsc$descriptor_s string = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
165*50bf276cStholo static short int DevChan;
166*50bf276cStholo static short int iosb[4];
167*50bf276cStholo
168*50bf276cStholo static long int i,status;
169*50bf276cStholo /* static char *retval; */
170*50bf276cStholo
171*50bf276cStholo
172*50bf276cStholo /* new VMSmunch variables */
173*50bf276cStholo
174*50bf276cStholo static int old_rtype=FAT$C_FIXED; /* storage for record type */
175*50bf276cStholo
176*50bf276cStholo
177*50bf276cStholo
178*50bf276cStholo /*---------------------------------------------------------------------------
179*50bf276cStholo Initialize attribute blocks, parse filename, resolve any wildcards, and
180*50bf276cStholo get the file info.
181*50bf276cStholo ---------------------------------------------------------------------------*/
182*50bf276cStholo
183*50bf276cStholo /* initialize RMS structures, we need a NAM to retrieve the FID */
184*50bf276cStholo Fab = cc$rms_fab;
185*50bf276cStholo Fab.fab$l_fna = filename;
186*50bf276cStholo Fab.fab$b_fns = strlen(filename);
187*50bf276cStholo Fab.fab$l_nam = &Nam; /* FAB has an associated NAM */
188*50bf276cStholo Nam = cc$rms_nam;
189*50bf276cStholo Nam.nam$l_esa = EName; /* expanded filename */
190*50bf276cStholo Nam.nam$b_ess = sizeof(EName);
191*50bf276cStholo Nam.nam$l_rsa = RName; /* resultant filename */
192*50bf276cStholo Nam.nam$b_rss = sizeof(RName);
193*50bf276cStholo
194*50bf276cStholo /* do $PARSE and $SEARCH here */
195*50bf276cStholo status = sys$parse(&Fab);
196*50bf276cStholo if (!(status & 1)) return(status);
197*50bf276cStholo
198*50bf276cStholo /* search for the first file.. If none signal error */
199*50bf276cStholo status = sys$search(&Fab);
200*50bf276cStholo if (!(status & 1)) return(status);
201*50bf276cStholo
202*50bf276cStholo while (status & 1) {
203*50bf276cStholo /* initialize Device name length, note that this points into the NAM
204*50bf276cStholo to get the device name filled in by the $PARSE, $SEARCH services */
205*50bf276cStholo DevDesc.dsc$w_length = Nam.nam$t_dvi[0];
206*50bf276cStholo
207*50bf276cStholo status = sys$assign(&DevDesc,&DevChan,0,0);
208*50bf276cStholo if (!(status & 1)) return(status);
209*50bf276cStholo
210*50bf276cStholo FileName.dsc$a_pointer = Nam.nam$l_name;
211*50bf276cStholo FileName.dsc$w_length = Nam.nam$b_name+Nam.nam$b_type+Nam.nam$b_ver;
212*50bf276cStholo
213*50bf276cStholo /* Initialize the FIB */
214*50bf276cStholo for (i=0;i<3;i++)
215*50bf276cStholo #ifdef VAXC
216*50bf276cStholo Fib.fib$r_fid_overlay.fib$w_fid[i]=Nam.nam$w_fid[i];
217*50bf276cStholo #else
218*50bf276cStholo Fib.fib$w_fid[i]=Nam.nam$w_fid[i];
219*50bf276cStholo #endif
220*50bf276cStholo for (i=0;i<3;i++)
221*50bf276cStholo #ifdef VAXC
222*50bf276cStholo Fib.fib$r_did_overlay.fib$w_did[i]=Nam.nam$w_did[i];
223*50bf276cStholo #else
224*50bf276cStholo Fib.fib$w_did[i]=Nam.nam$w_did[i];
225*50bf276cStholo #endif
226*50bf276cStholo
227*50bf276cStholo /* Use the IO$_ACCESS function to return info about the file */
228*50bf276cStholo /* Note, used this way, the file is not opened, and the expiration */
229*50bf276cStholo /* and revision dates are not modified */
230*50bf276cStholo status = sys$qiow(0,DevChan,IO$_ACCESS,&iosb,0,0,
231*50bf276cStholo &FibDesc,&FileName,0,0,&Atr,0);
232*50bf276cStholo if (!(status & 1))
233*50bf276cStholo {
234*50bf276cStholo sys$dassgn(DevChan);
235*50bf276cStholo return(status);
236*50bf276cStholo }
237*50bf276cStholo status = iosb[0];
238*50bf276cStholo if (!(status & 1))
239*50bf276cStholo {
240*50bf276cStholo sys$dassgn(DevChan);
241*50bf276cStholo return(status);
242*50bf276cStholo }
243*50bf276cStholo
244*50bf276cStholo /*-----------------------------------------------------------------------
245*50bf276cStholo We have the current information from the file: now see what user
246*50bf276cStholo wants done with it.
247*50bf276cStholo -----------------------------------------------------------------------*/
248*50bf276cStholo
249*50bf276cStholo switch (action) {
250*50bf276cStholo
251*50bf276cStholo case GET_TIMES:
252*50bf276cStholo asctim(((struct VMStimbuf *)ptr)->modtime, Cdate);
253*50bf276cStholo asctim(((struct VMStimbuf *)ptr)->actime, Rdate);
254*50bf276cStholo break;
255*50bf276cStholo
256*50bf276cStholo case SET_TIMES:
257*50bf276cStholo bintim(((struct VMStimbuf *)ptr)->modtime, Cdate);
258*50bf276cStholo bintim(((struct VMStimbuf *)ptr)->actime, Rdate);
259*50bf276cStholo break;
260*50bf276cStholo
261*50bf276cStholo case GET_RTYPE: /* non-modifying */
262*50bf276cStholo *(int *)ptr = Fat.RTYPE.fat$v_rtype;
263*50bf276cStholo return RMS$_NORMAL; /* return to user */
264*50bf276cStholo break;
265*50bf276cStholo
266*50bf276cStholo case CHANGE_RTYPE:
267*50bf276cStholo old_rtype = Fat.RTYPE.fat$v_rtype; /* save current one */
268*50bf276cStholo if ((*(int *)ptr < FAT$C_UNDEFINED) ||
269*50bf276cStholo (*(int *)ptr > FAT$C_STREAMCR))
270*50bf276cStholo Fat.RTYPE.fat$v_rtype = FAT$C_STREAMLF; /* Unix I/O happy */
271*50bf276cStholo else
272*50bf276cStholo Fat.RTYPE.fat$v_rtype = *(int *)ptr;
273*50bf276cStholo break;
274*50bf276cStholo
275*50bf276cStholo case RESTORE_RTYPE:
276*50bf276cStholo Fat.RTYPE.fat$v_rtype = old_rtype;
277*50bf276cStholo break;
278*50bf276cStholo
279*50bf276cStholo default:
280*50bf276cStholo return SS$_BADPARAM; /* anything better? */
281*50bf276cStholo }
282*50bf276cStholo
283*50bf276cStholo /*-----------------------------------------------------------------------
284*50bf276cStholo Go back and write modified data to the file header.
285*50bf276cStholo -----------------------------------------------------------------------*/
286*50bf276cStholo
287*50bf276cStholo /* note, part of the FIB was cleared by earlier QIOW, so reset it */
288*50bf276cStholo #ifdef VAXC
289*50bf276cStholo Fib.fib$r_acctl_overlay.fib$l_acctl = FIB$M_NORECORD;
290*50bf276cStholo #else
291*50bf276cStholo Fib.fib$l_acctl = FIB$M_NORECORD;
292*50bf276cStholo #endif
293*50bf276cStholo for (i=0;i<3;i++)
294*50bf276cStholo #ifdef VAXC
295*50bf276cStholo Fib.fib$r_fid_overlay.fib$w_fid[i]=Nam.nam$w_fid[i];
296*50bf276cStholo #else
297*50bf276cStholo Fib.fib$w_fid[i]=Nam.nam$w_fid[i];
298*50bf276cStholo #endif
299*50bf276cStholo for (i=0;i<3;i++)
300*50bf276cStholo #ifdef VAXC
301*50bf276cStholo Fib.fib$r_did_overlay.fib$w_did[i]=Nam.nam$w_did[i];
302*50bf276cStholo #else
303*50bf276cStholo Fib.fib$w_did[i]=Nam.nam$w_did[i];
304*50bf276cStholo #endif
305*50bf276cStholo
306*50bf276cStholo /* Use the IO$_MODIFY function to change info about the file */
307*50bf276cStholo /* Note, used this way, the file is not opened, however this would */
308*50bf276cStholo /* normally cause the expiration and revision dates to be modified. */
309*50bf276cStholo /* Using FIB$M_NORECORD prohibits this from happening. */
310*50bf276cStholo status = sys$qiow(0,DevChan,IO$_MODIFY,&iosb,0,0,
311*50bf276cStholo &FibDesc,&FileName,0,0,&Atr,0);
312*50bf276cStholo if (!(status & 1))
313*50bf276cStholo {
314*50bf276cStholo sys$dassgn(DevChan);
315*50bf276cStholo return(status);
316*50bf276cStholo }
317*50bf276cStholo
318*50bf276cStholo status = iosb[0];
319*50bf276cStholo if (!(status & 1))
320*50bf276cStholo {
321*50bf276cStholo sys$dassgn(DevChan);
322*50bf276cStholo return(status);
323*50bf276cStholo }
324*50bf276cStholo
325*50bf276cStholo status = sys$dassgn(DevChan);
326*50bf276cStholo if (!(status & 1)) return(status);
327*50bf276cStholo
328*50bf276cStholo /* look for next file, if none, no big deal.. */
329*50bf276cStholo status = sys$search(&Fab);
330*50bf276cStholo }
331*50bf276cStholo } /* end function VMSmunch() */
332*50bf276cStholo
333*50bf276cStholo
334*50bf276cStholo
335*50bf276cStholo
336*50bf276cStholo
337*50bf276cStholo /***********************/
338*50bf276cStholo /* Function bintim() */
339*50bf276cStholo /***********************/
340*50bf276cStholo
asctim(time,binval)341*50bf276cStholo void asctim(time,binval) /* convert 64-bit binval to string, put in time */
342*50bf276cStholo char *time;
343*50bf276cStholo long int binval[2];
344*50bf276cStholo {
345*50bf276cStholo static struct dsc$descriptor date_str={23,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
346*50bf276cStholo /* dsc$w_length, dsc$b_dtype, dsc$b_class, dsc$a_pointer */
347*50bf276cStholo
348*50bf276cStholo date_str.dsc$a_pointer = time;
349*50bf276cStholo sys$asctim(0, &date_str, binval, 0);
350*50bf276cStholo time[23] = '\0';
351*50bf276cStholo }
352*50bf276cStholo
353*50bf276cStholo
354*50bf276cStholo
355*50bf276cStholo
356*50bf276cStholo
357*50bf276cStholo /***********************/
358*50bf276cStholo /* Function bintim() */
359*50bf276cStholo /***********************/
360*50bf276cStholo
bintim(time,binval)361*50bf276cStholo void bintim(time,binval) /* convert time string to 64 bits, put in binval */
362*50bf276cStholo char *time;
363*50bf276cStholo long int binval[2];
364*50bf276cStholo {
365*50bf276cStholo static struct dsc$descriptor date_str={0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
366*50bf276cStholo
367*50bf276cStholo date_str.dsc$w_length = strlen(time);
368*50bf276cStholo date_str.dsc$a_pointer = time;
369*50bf276cStholo sys$bintim(&date_str, binval);
370*50bf276cStholo }
371