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