xref: /openbsd-src/gnu/usr.bin/cvs/vms/vmsmunch.c (revision 50bf276cd1c7e20f1eda64a5e63e0fae39e12a95)
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