whyever the aclocal call was commented out…
[alioth/cvs.git] / vms / vmsmunch.c
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
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
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
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 }