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