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 } 371