1/*
2  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.
3
4  See the accompanying file LICENSE, version 2007-Mar-4 or later
5  (the contents of which are also included in zip.h) for terms of use.
6  If, for some reason, all these files are missing, the Info-ZIP license
7  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
8*/
9
10/* 2004-12-13 SMS.
11 * Disabled the module name macro to accommodate old GNU C which didn't
12 * obey the directive, and thus confused MMS/MMK where the object
13 * library dependencies need to have the correct module name.
14 */
15#if 0
16# define module_name     VMSMUNCH
17# define module_version  "V1.3-4"
18#endif /* 0 */
19
20/*
21 *  Modified by:
22 *
23 *    v1.3.1        O.v.d.Linden, C. Spieler            04-JUL-1998 14:35
24 *            Modified check that decides on the type of definitions for
25 *            FIB$W_FID etc. to support GNU C.
26 *
27 *    v1.3          Hunter Goatley                      14-SEP-1992 08:51
28 *            Added definitions of FIB$W_FID, FIB$W_DID, and
29 *            FIB$L_ACCTL to allow for the fact that fibdef
30 *            contains variant_unions under Alpha.
31 */
32/*---------------------------------------------------------------------------
33
34  vmsmunch.c                    version 1.2                     28 Apr 1992
35
36  This routine is a blatant and unrepentent appropriation of all the nasty
37  and difficult-to-do and complicated VMS shenanigans which Joe Meadows has
38  so magnificently captured in his FILE utility.  Not only that, it's even
39  allowed! (see below).  But let it be clear at the outset that Joe did all
40  the work; yea, verily, he is truly a godlike unit.
41
42  The appropriations and modifications herein were performed primarily by
43  him known as "Cave Newt," although the Info-ZIP working group probably had
44  their fingers in it somewhere along the line.  The idea is to put the raw
45  power of Joe's original routine at the disposal of various routines used
46  by UnZip (and Zip, possibly), not least among them the utime() function.
47  Read on for details...
48
49        01-SEP-1994     Richard Levitte <levitte@e.kth.se>
50                        If one of the fields given to VMSmunch are NULL,
51                        do not update the corresponding daytime.
52
53        18-JUL-1994     Hunter Goatley <goathunter@WKU.EDU>
54                        Fixed IO$_ACCESS call.
55
56        18-Jul-1994     Richard Levitte levitte@e.kth.se
57                        Changed VMSmunch() to deassign the channel before
58                        returning when an error has occured.
59
60        02-Apr-1994     Jamie Hanrahan  jeh@cmkrnl.com
61                        Moved definition of VMStimbuf struct from here
62                        to vmsmunch.h
63  ---------------------------------------------------------------------------
64
65  Usage (i.e., "interface," in geek-speak):
66
67     int VMSmunch( char *filename, int action, char *ptr );
68
69     filename   the name of the file on which to be operated, obviously
70     action     an integer which specifies what action to take
71     ptr        pointer to any extra item which may be needed (else NULL)
72
73  The possible values for the action argument are as follows:
74
75     GET_TIMES      get the creation and revision dates of filename; ptr
76                    must point to an empty VMStimbuf struct, as defined
77                    in vmsmunch.h
78                    (with room for at least 24 characters, including term.)
79     SET_TIMES      set the creation and revision dates of filename (utime
80                    option); ptr must point to a valid VMStimbuf struct,
81                    as defined in vmsmunch.h
82     GET_RTYPE      get the record type of filename; ptr must point to an
83                    integer which, on return, is set to the type (as defined
84                    in vmsdefs.h:  FAT$C_* defines)
85     CHANGE_RTYPE   change the record type to that specified by the integer
86                    to which ptr points; save the old record type (later
87                    saves overwrite earlier ones)
88     RESTORE_RTYPE  restore the record type to the previously saved value;
89                    or, if none, set it to "fixed-length, 512-byte" record
90                    format (ptr not used)
91
92  ---------------------------------------------------------------------------
93
94  Comments from FILE.C, a utility to modify file characteristics:
95
96     Written by Joe Meadows Jr, at the Fred Hutchinson Cancer Research Center
97     BITNET: JOE@FHCRCVAX
98     PHONE: (206) 467-4970
99
100     There are no restrictions on this code, you may sell it, include it
101     with any commercial package, or feed it to a whale.. However, I would
102     appreciate it if you kept this comment in the source code so that anyone
103     receiving this code knows who to contact in case of problems. Note that
104     I do not demand this condition..
105
106  ---------------------------------------------------------------------------*/
107
108
109/* 2004-12-13 SMS.
110 * Disabled the module name macro to accommodate old GNU C which didn't
111 * obey the directive, and thus confused MMS/MMK where the object
112 * library dependencies need to have the correct module name.
113 */
114#if 0
115# if defined(__DECC) || defined(__GNUC__)
116#  pragma module module_name module_version
117# else
118#  module module_name module_version
119# endif
120#endif /* 0 */
121
122/*****************************/
123/*  Includes, Defines, etc.  */
124/*****************************/
125
126/* Accomodation for /NAMES = AS_IS with old header files. */
127
128#define sys$asctim SYS$ASCTIM
129#define sys$assign SYS$ASSIGN
130#define sys$bintim SYS$BINTIM
131#define sys$dassgn SYS$DASSGN
132#define sys$parse SYS$PARSE
133#define sys$qiow SYS$QIOW
134#define sys$search SYS$SEARCH
135
136#include "zip.h"
137
138#include <stdio.h>
139#include <string.h>
140#include <iodef.h>
141#include <starlet.h>
142#include <fibdef.h>   /* this gets created with the c3.0 compiler */
143
144/*
145 *  Under Alpha (DEC C in VAXC mode) and under `good old' VAXC, the FIB unions
146 *  are declared as variant_unions.  DEC C (Alpha) in ANSI modes and third
147 *  party compilers which do not support `variant_union' define preprocessor
148 *  symbols to `hide' the "intermediate union/struct" names from the
149 *  programmer's API.
150 *  We check the presence of these defines and for DEC's FIBDEF.H defining
151 *  __union as variant_union to make sure we access the structure correctly.
152 */
153#if defined(fib$w_did) || (defined(__union) && (__union == variant_union))
154#  define FIB$W_DID     fib$w_did
155#  define FIB$W_FID     fib$w_fid
156#  define FIB$L_ACCTL   fib$l_acctl
157#else
158#  define FIB$W_DID     fib$r_did_overlay.fib$w_did
159#  define FIB$W_FID     fib$r_fid_overlay.fib$w_fid
160#  define FIB$L_ACCTL   fib$r_acctl_overlay.fib$l_acctl
161#endif
162
163#include "vms.h"
164#include "vmsmunch.h"  /* GET/SET_TIMES, RTYPE, etc. */
165#include "vmsdefs.h"   /* fatdef.h, etc. */
166
167static void asctim(char *time, long int binval[2]);
168static void bintim(char *time, long int binval[2]);
169
170/* from <ssdef.h> */
171#ifndef SS$_NORMAL
172#  define SS$_NORMAL    1
173#  define SS$_BADPARAM  20
174#endif
175
176
177/* On VAX, define Goofy VAX Type-Cast to obviate /standard = vaxc.
178   Otherwise, lame system headers on VAX cause compiler warnings.
179   (GNU C may define vax but not __VAX.)
180*/
181#ifdef vax
182# define __VAX 1
183#endif /* def vax */
184
185#ifdef __VAX
186# define GVTC (unsigned int)
187#else /* def __VAX */
188# define GVTC
189#endif /* def __VAX */
190
191
192/*************************/
193/*  Function VMSmunch()  */
194/*************************/
195
196int VMSmunch(
197    char  *filename,
198    int   action,
199    char  *ptr )
200{
201
202    /* original file.c variables */
203
204    static struct FAB Fab;
205    static struct NAM_STRUCT Nam;
206    static struct fibdef Fib; /* short fib */
207
208    static struct dsc$descriptor FibDesc =
209      {sizeof(Fib),DSC$K_DTYPE_Z,DSC$K_CLASS_S,(char *)&Fib};
210    static struct dsc$descriptor_s DevDesc =
211      {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,&Nam.NAM_DVI[1]};
212    static struct fatdef Fat;
213    static union {
214      struct fchdef fch;
215      long int dummy;
216    } uchar;
217    static struct fjndef jnl;
218    static long int Cdate[2],Rdate[2],Edate[2],Bdate[2];
219    static short int revisions;
220    static unsigned long uic;
221#if defined(__DECC) || defined(__DECCXX)
222#pragma __member_alignment __save
223#pragma __nomember_alignment
224#endif /* __DECC || __DECCXX */
225    static union {
226      unsigned short int value;
227      struct {
228        unsigned system : 4;
229        unsigned owner : 4;
230        unsigned group : 4;
231        unsigned world : 4;
232      } bits;
233    } prot;
234#if defined(__DECC) || defined(__DECCXX)
235#pragma __member_alignment __restore
236#endif /* __DECC || __DECCXX */
237
238    static struct atrdef Atr[] = {
239      {sizeof(Fat),ATR$C_RECATTR, GVTC &Fat},          /* record attributes */
240      {sizeof(uchar),ATR$C_UCHAR, GVTC &uchar},    /* File characteristics */
241      {sizeof(Cdate),ATR$C_CREDATE, GVTC &Cdate[0]},   /* Creation date */
242      {sizeof(Rdate),ATR$C_REVDATE, GVTC &Rdate[0]},   /* Revision date */
243      {sizeof(Edate),ATR$C_EXPDATE, GVTC &Edate[0]},   /* Expiration date */
244      {sizeof(Bdate),ATR$C_BAKDATE, GVTC &Bdate[0]},   /* Backup date */
245      {sizeof(revisions),ATR$C_ASCDATES, GVTC &revisions}, /* number of revs */
246      {sizeof(prot),ATR$C_FPRO, GVTC &prot},           /* file protection  */
247      {sizeof(uic),ATR$C_UIC, GVTC &uic},              /* file owner */
248      {sizeof(jnl),ATR$C_JOURNAL, GVTC &jnl},          /* journal flags */
249      {0,0,0}
250    } ;
251
252    static char EName[NAM_MAXRSS];
253    static char RName[NAM_MAXRSS];
254    static struct dsc$descriptor_s FileName =
255      {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
256    static struct dsc$descriptor_s string = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
257    static short int DevChan;
258    static short int iosb[4];
259
260    static long int i,status;
261/*  static char *retval;  */
262
263
264    /* new VMSmunch variables */
265
266    static int  old_rtype=FAT$C_FIXED;   /* storage for record type */
267
268
269
270/*---------------------------------------------------------------------------
271    Initialize attribute blocks, parse filename, resolve any wildcards, and
272    get the file info.
273  ---------------------------------------------------------------------------*/
274
275    /* Initialize RMS structures.  We need a NAM[L] to retrieve the FID. */
276    Fab = cc$rms_fab;
277    Fab.fab$l_fna = filename;
278    Fab.fab$b_fns = strlen(filename);
279    Fab.FAB_NAM = &Nam; /* FAB has an associated NAM[L]. */
280    Nam = CC_RMS_NAM;
281    Nam.NAM_ESA = EName; /* expanded filename */
282    Nam.NAM_ESS = sizeof(EName);
283    Nam.NAM_RSA = RName; /* resultant filename */
284    Nam.NAM_RSS = sizeof(RName);
285
286    /* do $PARSE and $SEARCH here */
287    status = sys$parse(&Fab);
288    if (!(status & 1)) return(status);
289
290    /* search for the first file.. If none signal error */
291    status = sys$search(&Fab);
292    if (!(status & 1)) return(status);
293
294    while (status & 1) {
295        /* initialize Device name length, note that this points into the NAM[L]
296           to get the device name filled in by the $PARSE, $SEARCH services */
297        DevDesc.dsc$w_length = Nam.NAM_DVI[0];
298
299        status = sys$assign(&DevDesc,&DevChan,0,0);
300        if (!(status & 1)) return(status);
301
302        FileName.dsc$a_pointer = Nam.NAM_L_NAME;
303        FileName.dsc$w_length = Nam.NAM_B_NAME+Nam.NAM_B_TYPE+Nam.NAM_B_VER;
304
305        /* Initialize the FIB */
306        for (i=0;i<3;i++) {
307            Fib.FIB$W_FID[i]=Nam.NAM_FID[i];
308            Fib.FIB$W_DID[i]=Nam.NAM_DID[i];
309        }
310
311        /* Use the IO$_ACCESS function to return info about the file */
312        /* Note, used this way, the file is not opened, and the expiration */
313        /* and revision dates are not modified */
314        status = sys$qiow(0,DevChan,IO$_ACCESS,&iosb,0,0,
315                          &FibDesc,&FileName,0,0,&Atr,0);
316        if (!(status & 1) || !((status = iosb[0]) & 1)) {
317            sys$dassgn(DevChan);
318            return(status);
319        }
320
321    /*-----------------------------------------------------------------------
322        We have the current information from the file:  now see what user
323        wants done with it.
324      -----------------------------------------------------------------------*/
325
326        switch (action) {
327
328          case GET_TIMES:   /* non-modifying */
329              asctim(((struct VMStimbuf *)ptr)->modtime, Cdate);
330              asctim(((struct VMStimbuf *)ptr)->actime, Rdate);
331              sys$dassgn(DevChan);
332              return RMS$_NORMAL;     /* return to user */
333              break;
334
335          case SET_TIMES:
336              if (((struct VMStimbuf *)ptr)->modtime != (char *)NULL)
337                  bintim(((struct VMStimbuf *)ptr)->modtime, Cdate);
338              if (((struct VMStimbuf *)ptr)->actime != (char *)NULL)
339                  bintim(((struct VMStimbuf *)ptr)->actime, Rdate);
340              break;
341
342          case GET_RTYPE:   /* non-modifying */
343              *(int *)ptr = Fat.fat$v_rtype;
344              sys$dassgn(DevChan);
345              return RMS$_NORMAL;     /* return to user */
346              break;
347
348          case CHANGE_RTYPE:
349              old_rtype = Fat.fat$v_rtype;              /* save current one */
350              if ((*(int *)ptr < FAT$C_UNDEFINED) ||
351                  (*(int *)ptr > FAT$C_STREAMCR))
352                  Fat.fat$v_rtype = FAT$C_STREAMLF;       /* Unix I/O happy */
353              else
354                  Fat.fat$v_rtype = *(int *)ptr;
355              break;
356
357          case RESTORE_RTYPE:
358              Fat.fat$v_rtype = old_rtype;
359              break;
360
361          default:
362              sys$dassgn(DevChan);
363              return SS$_BADPARAM;   /* anything better? */
364        }
365
366    /*-----------------------------------------------------------------------
367        Go back and write modified data to the file header.
368      -----------------------------------------------------------------------*/
369
370        /* note, part of the FIB was cleared by earlier QIOW, so reset it */
371        Fib.FIB$L_ACCTL = FIB$M_NORECORD;
372        for (i=0;i<3;i++) {
373            Fib.FIB$W_FID[i]=Nam.NAM_FID[i];
374            Fib.FIB$W_DID[i]=Nam.NAM_DID[i];
375        }
376
377        /* Use the IO$_MODIFY function to change info about the file */
378        /* Note, used this way, the file is not opened, however this would */
379        /* normally cause the expiration and revision dates to be modified. */
380        /* Using FIB$M_NORECORD prohibits this from happening. */
381        status = sys$qiow(0,DevChan,IO$_MODIFY,&iosb,0,0,
382                          &FibDesc,&FileName,0,0,&Atr,0);
383        if (!(status & 1) || !((status = iosb[0]) & 1)) {
384            sys$dassgn(DevChan);
385            return(status);
386        }
387
388        status = sys$dassgn(DevChan);
389        if (!(status & 1)) return(status);
390
391        /* look for next file, if none, no big deal.. */
392        status = sys$search(&Fab);
393    }
394    return(status);
395} /* end function VMSmunch() */
396
397
398
399
400
401/***********************/
402/*  Function asctim()  */
403/***********************/
404
405static void asctim(        /* convert 64-bit binval to string, put in time */
406    char *time,
407    long int binval[2] )
408{
409    static struct dsc$descriptor date_str={23,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
410      /* dsc$w_length, dsc$b_dtype, dsc$b_class, dsc$a_pointer */
411
412    date_str.dsc$a_pointer = time;
413    sys$asctim(0, &date_str, binval, 0);
414    time[23] = '\0';
415}
416
417
418
419
420
421/***********************/
422/*  Function bintim()  */
423/***********************/
424
425static void bintim(        /* convert time string to 64 bits, put in binval */
426    char *time,
427    long int binval[2] )
428{
429    static struct dsc$descriptor date_str={0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
430
431    date_str.dsc$w_length = strlen(time);
432    date_str.dsc$a_pointer = time;
433    sys$bintim(&date_str, binval);
434}
435