vmsmunch.c 15 KB

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