vms_im.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926
  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. /*
  9. * vms_im.c (zip) by Igor Mandrichenko Version 2.2-2
  10. *
  11. * Revision history:
  12. * ...
  13. * 2.1-1 16-feb-1993 I.Mandrichenko
  14. * Get file size from XABFHC and check bytes rest in file before
  15. * reading.
  16. * 2.1-2 2-mar-1993 I.Mandrichenko
  17. * Make code more standard
  18. * 2.2 21-jun-1993 I.Mandrichenko
  19. * Free all allocated space, use more static storage.
  20. * Use memcompress() from bits.c (deflation) for block compression.
  21. * To revert to old compression method #define OLD_COMPRESS
  22. * 2.2-2 28-sep-1995 C.Spieler
  23. * Reorganized code for easier maintance of the two incompatible
  24. * flavours (IM style and PK style) VMS attribute support.
  25. * Generic functions (common to both flavours) are now collected
  26. * in a `wrapper' source file that includes one of the VMS attribute
  27. * handlers.
  28. * 3.0 23-Oct-2004 Steven Schweda
  29. * Changed to maintain compatibility with VMS_PK.C. Note that
  30. * reading with sys$read() prevents getting any data past EOF,
  31. * regardless of appearances. Moved the VMS_PK_EXTRA test into
  32. * here from VMS.C to allow more general automatic dependency
  33. * generation.
  34. * 17-Feb-2005 Steven Schweda
  35. * Added support for ODS5 extended names.
  36. */
  37. #ifdef VMS /* For VMS only ! */
  38. #ifndef VMS_PK_EXTRA
  39. #define OLD_COMPRESS /*To use old compression method define it.*/
  40. #ifdef VMS_ZIP
  41. #undef VMS_ZIP /* do NOT include PK style Zip definitions */
  42. #endif
  43. #include "vms.h"
  44. #ifndef __LIB$ROUTINES_LOADED
  45. #include <lib$routines.h>
  46. #endif
  47. #ifndef UTIL
  48. #define RET_ERROR 1
  49. #define RET_SUCCESS 0
  50. #define RET_EOF 0
  51. #define Kbyte 1024
  52. typedef struct XAB *xabptr;
  53. /*
  54. * Block sizes
  55. */
  56. #define EXTL0 ((FABL + EXTHL)+ \
  57. (XFHCL + EXTHL)+ \
  58. (XPROL + EXTHL)+ \
  59. (XDATL + EXTHL)+ \
  60. (XRDTL + EXTHL))
  61. #ifdef OLD_COMPRESS
  62. #define PAD sizeof(uch)
  63. #else
  64. #define PAD 10*sizeof(ush) /* Two extra bytes for compr. header */
  65. #endif
  66. #define PAD0 (5*PAD) /* Reserve space for the case when
  67. * compression fails */
  68. static int _compress(uch *from, uch *to, int size);
  69. #ifdef DEBUG
  70. static void dump_rms_block(uch *p);
  71. #endif /* DEBUG */
  72. /********************************
  73. * Function set_extra_field *
  74. ********************************/
  75. /*
  76. | 2004-11-11 SMS.
  77. | Changed to use separate storage for ->extra and ->cextra. Zip64
  78. | processing may move (reallocate) one and not the other.
  79. */
  80. static uch *_compress_block(register struct IZ_block *to,
  81. uch *from, int size, char *sig);
  82. static int get_vms_version(char *verbuf, int len);
  83. int set_extra_field(z, z_utim)
  84. struct zlist far *z;
  85. iztimes *z_utim;
  86. /*
  87. * Get file VMS file attributes and store them into extent fields.
  88. * Store VMS version also.
  89. * On error leave z intact.
  90. */
  91. {
  92. int status;
  93. uch *xtra;
  94. uch *cxtra;
  95. uch *scan;
  96. extent extra_l;
  97. static struct FAB fab;
  98. static struct NAM_STRUCT nam;
  99. static struct XABSUM xabsum;
  100. static struct XABFHC xabfhc;
  101. static struct XABDAT xabdat;
  102. static struct XABPRO xabpro;
  103. static struct XABRDT xabrdt;
  104. xabptr x = (xabptr)NULL, xab_chain = (xabptr)NULL, last_xab = (xabptr)NULL;
  105. int nk, na;
  106. int i;
  107. int rc=RET_ERROR;
  108. char verbuf[80];
  109. int verlen = 0;
  110. if (!vms_native)
  111. {
  112. #ifdef USE_EF_UT_TIME
  113. /*
  114. * A `portable' zipfile entry is created. Create an "UT" extra block
  115. * containing UNIX style modification time stamp in UTC, which helps
  116. * maintaining the `real' "last modified" time when the archive is
  117. * transfered across time zone boundaries.
  118. */
  119. # ifdef IZ_CHECK_TZ
  120. if (!zp_tz_is_valid)
  121. return ZE_OK; /* skip silently if no valid TZ info */
  122. # endif
  123. if ((xtra = (uch *) malloc( EB_HEADSIZE+ EB_UT_LEN( 1))) == NULL)
  124. return ZE_MEM;
  125. if ((cxtra = (uch *) malloc( EB_HEADSIZE+ EB_UT_LEN( 1))) == NULL)
  126. return ZE_MEM;
  127. /* Fill xtra[] with data. */
  128. xtra[ 0] = 'U';
  129. xtra[ 1] = 'T';
  130. xtra[ 2] = EB_UT_LEN(1); /* length of data part of e.f. */
  131. xtra[ 3] = 0;
  132. xtra[ 4] = EB_UT_FL_MTIME;
  133. xtra[ 5] = (uch) (z_utim->mtime);
  134. xtra[ 6] = (uch) (z_utim->mtime >> 8);
  135. xtra[ 7] = (uch) (z_utim->mtime >> 16);
  136. xtra[ 8] = (uch) (z_utim->mtime >> 24);
  137. /* Copy xtra[] data into cxtra[]. */
  138. memcpy( cxtra, xtra, (EB_HEADSIZE+ EB_UT_LEN( 1)));
  139. /* Set sizes and pointers. */
  140. z->cext = z->ext = (EB_HEADSIZE+ EB_UT_LEN( 1));
  141. z->extra = (char *) xtra;
  142. z->cextra = (char *) cxtra;
  143. #endif /* USE_EF_UT_TIME */
  144. return RET_SUCCESS;
  145. }
  146. /*
  147. * Initialize RMS control blocks and link them
  148. */
  149. fab = cc$rms_fab;
  150. nam = CC_RMS_NAM;
  151. xabsum = cc$rms_xabsum;
  152. xabdat = cc$rms_xabdat;
  153. xabfhc = cc$rms_xabfhc;
  154. xabpro = cc$rms_xabpro;
  155. xabrdt = cc$rms_xabrdt;
  156. fab.FAB_NAM = &nam;
  157. fab.fab$l_xab = (char*)&xabsum;
  158. /*
  159. * Open the file and read summary information.
  160. */
  161. #ifdef NAML$C_MAXRSS
  162. fab.fab$l_dna = (char *) -1; /* Using NAML for default name. */
  163. fab.fab$l_fna = (char *) -1; /* Using NAML for file name. */
  164. #endif /* def NAML$C_MAXRSS */
  165. FAB_OR_NAML( fab, nam).FAB_OR_NAML_FNA = z->name;
  166. FAB_OR_NAML( fab, nam).FAB_OR_NAML_FNS = strlen( z->name);
  167. #ifdef NAML$M_OPEN_SPECIAL
  168. /* 2007-02-28 SMS.
  169. * If processing symlinks as symlinks ("-y"), then $OPEN the
  170. * link, not the target file.
  171. *
  172. * (nam.naml$v_open_special gets us the symlink itself instead of
  173. * its target. fab.fab$v_bio is necessary to allow sys$open() to
  174. * work. Without it, you get status %x0001860c, "%RMS-F-ORG,
  175. * invalid file organization value".)
  176. */
  177. if (linkput)
  178. {
  179. nam.naml$v_open_special = 1;
  180. fab.fab$v_bio = 1;
  181. }
  182. #endif /* def NAML$M_OPEN_SPECIAL */
  183. status = sys$open(&fab);
  184. if (ERR(status))
  185. {
  186. #ifdef DEBUG
  187. printf("set_extra_field: sys$open for file %s:\n error status = %d\n",
  188. z->name, status);
  189. #endif
  190. goto err_exit;
  191. }
  192. nk = xabsum.xab$b_nok;
  193. na = xabsum.xab$b_noa;
  194. #ifdef DEBUG
  195. printf("%d keys, %d alls\n", nk, na);
  196. #endif
  197. /*
  198. * Allocate XABKEY and XABALL blocks and link them
  199. */
  200. xabfhc.xab$l_nxt = (char*)&xabdat;
  201. xabdat.xab$l_nxt = (char*)&xabpro;
  202. xabpro.xab$l_nxt = (char*)&xabrdt;
  203. xabrdt.xab$l_nxt = NULL;
  204. xab_chain = (xabptr)(&xabfhc);
  205. last_xab = (xabptr)(&xabrdt);
  206. #define INIT(ptr,size,type,init) \
  207. if ( (ptr = (type *)malloc(size)) == NULL ) \
  208. { \
  209. printf( "set_extra_field: Insufficient memory.\n" ); \
  210. goto err_exit; \
  211. } \
  212. *(ptr) = (init);
  213. /*
  214. * Allocate and initialize all needed XABKEYs and XABALLs
  215. */
  216. for (i = 0; i < nk; i++)
  217. {
  218. struct XABKEY *k;
  219. INIT(k, XKEYL, struct XABKEY, cc$rms_xabkey);
  220. k->xab$b_ref = i;
  221. if (last_xab != NULL)
  222. last_xab->xab$l_nxt = (char*)k;
  223. last_xab = (xabptr)k;
  224. }
  225. for (i = 0; i < na; i++)
  226. {
  227. struct XABALL *a;
  228. INIT(a, XALLL, struct XABALL, cc$rms_xaball);
  229. a->xab$b_aid = i;
  230. if (last_xab != NULL)
  231. last_xab->xab$l_nxt = (char*)a;
  232. last_xab = (xabptr)a;
  233. }
  234. fab.fab$l_xab = (char*)xab_chain;
  235. #ifdef DEBUG
  236. printf("Dump of XAB chain before $DISPLAY:\n");
  237. for (x = xab_chain; x != NULL; x = x->xab$l_nxt)
  238. dump_rms_block((uch *)x);
  239. #endif
  240. /*
  241. * Get information on the file structure etc.
  242. */
  243. status = sys$display(&fab, 0, 0);
  244. if (ERR(status))
  245. {
  246. #ifdef DEBUG
  247. printf("set_extra_field: sys$display for file %s:\n error status = %d\n",
  248. z->name, status);
  249. #endif
  250. goto err_exit;
  251. }
  252. #ifdef DEBUG
  253. printf("\nDump of XAB chain after $DISPLAY:\n");
  254. for (x = xab_chain; x != NULL; x = x->xab$l_nxt)
  255. dump_rms_block((uch *)x);
  256. #endif
  257. fab.fab$l_xab = NULL; /* Keep XABs */
  258. status = sys$close(&fab);
  259. if (ERR(status))
  260. {
  261. #ifdef DEBUG
  262. printf("set_extra_field: sys$close for file %s:\n error status = %d\n",
  263. z->name, status);
  264. #endif
  265. goto err_exit;
  266. }
  267. extra_l = EXTL0 + nk * (XKEYL + EXTHL) + na * (XALLL + EXTHL);
  268. #ifndef OLD_COMPRESS
  269. extra_l += PAD0 + (nk+na) * PAD;
  270. #endif
  271. if ( (verlen = get_vms_version(verbuf, sizeof(verbuf))) > 0 )
  272. {
  273. extra_l += verlen + EXTHL;
  274. #ifndef OLD_COMPRESS
  275. extra_l += PAD;
  276. #endif
  277. }
  278. if ((scan = xtra = (uch *) malloc( extra_l)) == (uch*)NULL)
  279. {
  280. #ifdef DEBUG
  281. printf(
  282. "set_extra_field: Insufficient memory to allocate extra L buffer\n");
  283. #endif
  284. goto err_exit;
  285. }
  286. if ((cxtra = (uch *) malloc( extra_l)) == (uch*)NULL)
  287. {
  288. #ifdef DEBUG
  289. printf(
  290. "set_extra_field: Insufficient memory to allocate extra C buffer\n");
  291. #endif
  292. goto err_exit;
  293. }
  294. if (verlen > 0)
  295. scan = _compress_block((struct IZ_block *)scan, (uch *)verbuf,
  296. verlen, VERSIG);
  297. /*
  298. * Zero all unusable fields to improve compression
  299. */
  300. fab.fab$b_fns = fab.fab$b_shr = fab.fab$b_dns = fab.fab$b_fac = 0;
  301. fab.fab$w_ifi = 0;
  302. fab.fab$l_stv = fab.fab$l_sts = fab.fab$l_ctx = 0;
  303. fab.fab$l_dna = NULL;
  304. fab.fab$l_fna = NULL;
  305. fab.fab$l_nam = NULL;
  306. #ifdef NAML$C_MAXRSS
  307. fab.fab$l_naml = NULL;
  308. #endif /* def NAML$C_MAXRSS */
  309. fab.fab$l_xab = NULL;
  310. #ifdef DEBUG
  311. dump_rms_block( (uch *)&fab );
  312. #endif
  313. scan = _compress_block((struct IZ_block *)scan, (uch *)&fab, FABL, FABSIG);
  314. for (x = xab_chain; x != NULL;)
  315. {
  316. int bln;
  317. char *sig;
  318. xabptr next;
  319. next = (xabptr)(x->xab$l_nxt);
  320. x->xab$l_nxt = 0;
  321. switch (x->xab$b_cod)
  322. {
  323. case XAB$C_ALL:
  324. bln = XALLL;
  325. sig = XALLSIG;
  326. break;
  327. case XAB$C_KEY:
  328. bln = XKEYL;
  329. sig = XKEYSIG;
  330. break;
  331. case XAB$C_PRO:
  332. bln = XPROL;
  333. sig = XPROSIG;
  334. break;
  335. case XAB$C_FHC:
  336. bln = XFHCL;
  337. sig = XFHCSIG;
  338. break;
  339. case XAB$C_DAT:
  340. bln = XDATL;
  341. sig = XDATSIG;
  342. break;
  343. case XAB$C_RDT:
  344. bln = XRDTL;
  345. sig = XRDTSIG;
  346. break;
  347. default:
  348. bln = 0;
  349. sig = 0L;
  350. break;
  351. }
  352. if (bln > 0)
  353. scan = _compress_block((struct IZ_block *)scan, (uch *)x,
  354. bln, sig);
  355. x = next;
  356. }
  357. /* Copy xtra[] data into cxtra[]. */
  358. memcpy( cxtra, xtra, (scan- xtra));
  359. /* Set sizes and pointers. */
  360. z->cext = z->ext = scan- xtra;
  361. z->extra = (char*) xtra;
  362. z->cextra = (char*) cxtra;
  363. rc = RET_SUCCESS;
  364. err_exit:
  365. /*
  366. * Give up all allocated blocks
  367. */
  368. for (x = (struct XAB *)xab_chain; x != NULL; )
  369. {
  370. struct XAB *next;
  371. next = (xabptr)(x->xab$l_nxt);
  372. if (x->xab$b_cod == XAB$C_ALL || x->xab$b_cod == XAB$C_KEY)
  373. free(x);
  374. x = next;
  375. }
  376. return rc;
  377. }
  378. static int get_vms_version(verbuf, len)
  379. char *verbuf;
  380. int len;
  381. {
  382. int i = SYI$_VERSION;
  383. int verlen = 0;
  384. struct dsc$descriptor version;
  385. char *m;
  386. version.dsc$a_pointer = verbuf;
  387. version.dsc$w_length = len - 1;
  388. version.dsc$b_dtype = DSC$K_DTYPE_B;
  389. version.dsc$b_class = DSC$K_CLASS_S;
  390. if (ERR(lib$getsyi(&i, 0, &version, &verlen, 0, 0)) || verlen == 0)
  391. return 0;
  392. /* Cut out trailing spaces "V5.4-3 " -> "V5.4-3" */
  393. for (m = verbuf + verlen, i = verlen - 1; i > 0 && verbuf[i] == ' '; --i)
  394. --m;
  395. *m = 0;
  396. /* Cut out release number "V5.4-3" -> "V5.4" */
  397. if ((m = strrchr(verbuf, '-')) != NULL)
  398. *m = 0;
  399. return strlen(verbuf) + 1; /* Transmit ending 0 too */
  400. }
  401. #define CTXSIG ((ulg)('CtXx'))
  402. typedef struct user_context
  403. {
  404. ulg sig;
  405. struct FAB *fab;
  406. struct NAM_STRUCT *nam;
  407. struct RAB *rab;
  408. uzoff_t size;
  409. uzoff_t rest;
  410. int status;
  411. } Ctx, *Ctxptr;
  412. Ctx init_ctx =
  413. {
  414. CTXSIG,
  415. NULL,
  416. NULL,
  417. NULL,
  418. 0L,
  419. 0L,
  420. 0
  421. };
  422. #define CTXL sizeof(Ctx)
  423. #define CHECK_RAB(_r) ( (_r) != NULL && \
  424. (_r) -> rab$b_bid == RAB$C_BID && \
  425. (_r) -> rab$b_bln == RAB$C_BLN && \
  426. (_r) -> rab$l_ctx != 0 && \
  427. (_r) -> rab$l_fab != NULL )
  428. #define BLOCK_BYTES 512
  429. /**************************
  430. * Function vms_open *
  431. **************************/
  432. struct RAB *vms_open(name)
  433. char *name;
  434. {
  435. struct FAB *fab;
  436. struct NAM_STRUCT *nam;
  437. struct RAB *rab;
  438. struct XABFHC *fhc;
  439. Ctxptr ctx;
  440. if ((fab = (struct FAB *) malloc(FABL)) == NULL)
  441. return NULL;
  442. if ((nam =
  443. (struct NAM_STRUCT *) malloc( sizeof( struct NAM_STRUCT))) == NULL)
  444. {
  445. free(fab);
  446. return NULL;
  447. }
  448. if ((rab = (struct RAB *) malloc(RABL)) == NULL)
  449. {
  450. free(fab);
  451. free(nam);
  452. return NULL;
  453. }
  454. if ((fhc = (struct XABFHC *) malloc(XFHCL)) == (struct XABFHC *)NULL)
  455. {
  456. free(fab);
  457. free(nam);
  458. free(rab);
  459. return (struct RAB *)NULL;
  460. }
  461. if ((ctx = (Ctxptr) malloc(CTXL)) == (Ctxptr)NULL)
  462. {
  463. free(fab);
  464. free(nam);
  465. free(rab);
  466. free(fhc);
  467. return (struct RAB *)NULL;
  468. }
  469. *fab = cc$rms_fab;
  470. *nam = CC_RMS_NAM;
  471. *rab = cc$rms_rab;
  472. *fhc = cc$rms_xabfhc;
  473. fab->FAB_NAM = nam;
  474. #ifdef NAML$C_MAXRSS
  475. fab->fab$l_dna = (char *) -1; /* Using NAML for default name. */
  476. fab->fab$l_fna = (char *) -1; /* Using NAML for file name. */
  477. #endif /* def NAML$C_MAXRSS */
  478. FAB_OR_NAML( fab, nam)->FAB_OR_NAML_FNA = name;
  479. FAB_OR_NAML( fab, nam)->FAB_OR_NAML_FNS = strlen( name);
  480. fab->fab$b_fac = FAB$M_GET | FAB$M_BIO;
  481. fab->fab$l_xab = (char*)fhc;
  482. #ifdef NAML$M_OPEN_SPECIAL
  483. /* 2007-02-28 SMS.
  484. * If processing symlinks as symlinks ("-y"), then $OPEN the
  485. * link, not the target file. (Note that here the required
  486. * fab->fab$v_bio flag was set above.)
  487. */
  488. if (linkput)
  489. {
  490. nam->naml$v_open_special = 1;
  491. }
  492. #endif /* def NAML$M_OPEN_SPECIAL */
  493. if (ERR(sys$open(fab)))
  494. {
  495. sys$close(fab);
  496. free(fab);
  497. free(nam);
  498. free(rab);
  499. free(fhc);
  500. free(ctx);
  501. return (struct RAB *)NULL;
  502. }
  503. rab->rab$l_fab = fab;
  504. rab->rab$l_rop = RAB$M_BIO;
  505. if (ERR(sys$connect(rab)))
  506. {
  507. sys$close(fab);
  508. free(fab);
  509. free(nam);
  510. free(rab);
  511. free(ctx);
  512. return (struct RAB *)NULL;
  513. }
  514. *ctx = init_ctx;
  515. ctx->fab = fab;
  516. ctx->nam = nam;
  517. ctx->rab = rab;
  518. if (fhc->xab$l_ebk == 0)
  519. {
  520. /* Only known size is all allocated blocks.
  521. (This occurs with a zero-length file, for example.)
  522. */
  523. ctx->size =
  524. ctx->rest = ((uzoff_t) fhc->xab$l_hbk)* BLOCK_BYTES;
  525. }
  526. else
  527. {
  528. /* Store normal (used) size in ->size.
  529. If only one -V, store normal (used) size in ->rest.
  530. If -VV, store allocated-blocks size in ->rest.
  531. */
  532. ctx->size =
  533. (((uzoff_t) fhc->xab$l_ebk)- 1)* BLOCK_BYTES+ fhc->xab$w_ffb;
  534. if (vms_native < 2)
  535. ctx->rest = ctx->size;
  536. else
  537. ctx->rest = ((uzoff_t) fhc->xab$l_hbk)* BLOCK_BYTES;
  538. }
  539. free(fhc);
  540. fab->fab$l_xab = NULL;
  541. rab->rab$l_ctx = (unsigned) ctx;
  542. return rab;
  543. }
  544. /**************************
  545. * Function vms_close *
  546. **************************/
  547. int vms_close(rab)
  548. struct RAB *rab;
  549. {
  550. struct FAB *fab;
  551. struct NAM_STRUCT *nam;
  552. Ctxptr ctx;
  553. if (!CHECK_RAB(rab))
  554. return RET_ERROR;
  555. fab = (ctx = (Ctxptr)(rab->rab$l_ctx))->fab;
  556. nam = (ctx = (Ctxptr)(rab->rab$l_ctx))->nam;
  557. sys$close(fab);
  558. free(fab);
  559. free(nam);
  560. free(rab);
  561. free(ctx);
  562. return RET_SUCCESS;
  563. }
  564. /**************************
  565. * Function vms_rewind *
  566. **************************/
  567. int vms_rewind(rab)
  568. struct RAB *rab;
  569. {
  570. Ctxptr ctx;
  571. int status;
  572. if (!CHECK_RAB(rab))
  573. return RET_ERROR;
  574. ctx = (Ctxptr) (rab->rab$l_ctx);
  575. if (ERR(status = sys$rewind(rab)))
  576. {
  577. ctx->status = status;
  578. return RET_ERROR;
  579. }
  580. ctx->status = 0;
  581. ctx->rest = ctx->size;
  582. return RET_SUCCESS;
  583. }
  584. #define KByte (2* BLOCK_BYTES)
  585. #define MAX_READ_BYTES (32* KByte)
  586. /**************************
  587. * Function vms_read *
  588. **************************/
  589. size_t vms_read(rab, buf, size)
  590. struct RAB *rab;
  591. char *buf;
  592. size_t size;
  593. /*
  594. * size must be greater or equal to 512 !
  595. */
  596. {
  597. int status;
  598. Ctxptr ctx;
  599. ctx = (Ctxptr)rab->rab$l_ctx;
  600. if (!CHECK_RAB(rab))
  601. return 0;
  602. if (ctx -> rest == 0)
  603. return 0; /* Eof */
  604. /* If request is smaller than a whole block, fail.
  605. This really should never happen. (assert()?)
  606. */
  607. if (size < BLOCK_BYTES)
  608. return 0;
  609. /* 2004-09-27 SMS.
  610. Code here now resembles low-level QIO code in VMS_PK.C, but I
  611. doubt that sys$read() will actually get past the official EOF.
  612. */
  613. /* Adjust request size as appropriate. */
  614. if (size > MAX_READ_BYTES)
  615. {
  616. /* Restrict request to MAX_READ_BYTES. */
  617. size = MAX_READ_BYTES;
  618. }
  619. else
  620. {
  621. /* Round odd-ball request up to the next whole block.
  622. This really should never happen. (assert()?)
  623. */
  624. size = (size+ BLOCK_BYTES- 1)& ~(BLOCK_BYTES- 1);
  625. }
  626. /* Reduce "size" when next (last) read would overrun the EOF,
  627. but never below one byte (so we'll always get a nice EOF).
  628. */
  629. if (size > ctx->rest)
  630. size = ctx->rest;
  631. if (size == 0)
  632. size = 1;
  633. rab->rab$l_ubf = buf;
  634. rab->rab$w_usz = size;
  635. status = sys$read(rab);
  636. if (!ERR(status) && rab->rab$w_rsz > 0)
  637. {
  638. ctx -> status = 0;
  639. ctx -> rest -= rab->rab$w_rsz;
  640. return rab->rab$w_rsz;
  641. }
  642. else
  643. {
  644. ctx->status = (status==RMS$_EOF ? 0:status);
  645. if (status == RMS$_EOF)
  646. ctx -> rest = 0;
  647. return 0;
  648. }
  649. }
  650. /**************************
  651. * Function vms_error *
  652. **************************/
  653. int vms_error(rab)
  654. struct RAB *rab;
  655. {
  656. if (!CHECK_RAB(rab))
  657. return RET_ERROR;
  658. return ((Ctxptr) (rab->rab$l_ctx))->status;
  659. }
  660. #ifdef DEBUG
  661. static void dump_rms_block(p)
  662. uch *p;
  663. {
  664. uch bid, len;
  665. int err;
  666. char *type;
  667. char buf[132];
  668. int i;
  669. err = 0;
  670. bid = p[0];
  671. len = p[1];
  672. switch (bid)
  673. {
  674. case FAB$C_BID:
  675. type = "FAB";
  676. break;
  677. case XAB$C_ALL:
  678. type = "xabALL";
  679. break;
  680. case XAB$C_KEY:
  681. type = "xabKEY";
  682. break;
  683. case XAB$C_DAT:
  684. type = "xabDAT";
  685. break;
  686. case XAB$C_RDT:
  687. type = "xabRDT";
  688. break;
  689. case XAB$C_FHC:
  690. type = "xabFHC";
  691. break;
  692. case XAB$C_PRO:
  693. type = "xabPRO";
  694. break;
  695. default:
  696. type = "Unknown";
  697. err = 1;
  698. break;
  699. }
  700. printf("Block @%08X of type %s (%d).", p, type, bid);
  701. if (err)
  702. {
  703. printf("\n");
  704. return;
  705. }
  706. printf(" Size = %d\n", len);
  707. printf(" Offset - Hex - Dec\n");
  708. for (i = 0; i < len; i += 8)
  709. {
  710. int j;
  711. printf("%3d - ", i);
  712. for (j = 0; j < 8; j++)
  713. if (i + j < len)
  714. printf("%02X ", p[i + j]);
  715. else
  716. printf(" ");
  717. printf(" - ");
  718. for (j = 0; j < 8; j++)
  719. if (i + j < len)
  720. printf("%03d ", p[i + j]);
  721. else
  722. printf(" ");
  723. printf("\n");
  724. }
  725. }
  726. #endif /* DEBUG */
  727. #ifdef OLD_COMPRESS
  728. # define BC_METHOD EB_IZVMS_BC00
  729. # define COMP_BLK(to,tos,from,froms) _compress( from,to,froms )
  730. #else
  731. # define BC_METHOD EB_IZVMS_BCDEFL
  732. # define COMP_BLK(to,tos,from,froms) memcompress(to,tos,from,froms)
  733. #endif
  734. static uch *_compress_block(to,from,size,sig)
  735. register struct IZ_block *to;
  736. uch *from;
  737. int size;
  738. char *sig;
  739. {
  740. ulg cl;
  741. to -> sig = *(ush*)IZ_SIGNATURE;
  742. to -> bid = *(ulg*)(sig);
  743. to -> flags = BC_METHOD;
  744. to -> length = size;
  745. #ifdef DEBUG
  746. printf("\nmemcompr(%d,%d,%d,%d)\n",&(to->body[0]),size+PAD,from,size);
  747. #endif
  748. cl = COMP_BLK( &(to->body[0]), size+PAD, from, size );
  749. #ifdef DEBUG
  750. printf("Compressed to %d\n",cl);
  751. #endif
  752. if (cl >= size)
  753. {
  754. memcpy(&(to->body[0]), from, size);
  755. to->flags = EB_IZVMS_BCSTOR;
  756. cl = size;
  757. #ifdef DEBUG
  758. printf("Storing block...\n");
  759. #endif
  760. }
  761. return (uch*)(to) + (to->size = cl + EXTBSL + RESL) + EB_HEADSIZE;
  762. }
  763. #define NBITS 32
  764. static int _compress(from,to,size)
  765. uch *from,*to;
  766. int size;
  767. {
  768. int off=0;
  769. ulg bitbuf=0;
  770. int bitcnt=0;
  771. int i;
  772. #define _BIT(val,len) { \
  773. if (bitcnt + (len) > NBITS) \
  774. while(bitcnt >= 8) \
  775. { \
  776. to[off++] = (uch)bitbuf; \
  777. bitbuf >>= 8; \
  778. bitcnt -= 8; \
  779. } \
  780. bitbuf |= ((ulg)(val))<<bitcnt; \
  781. bitcnt += len; \
  782. }
  783. #define _FLUSH { \
  784. while(bitcnt>0) \
  785. { \
  786. to[off++] = (uch)bitbuf; \
  787. bitbuf >>= 8; \
  788. bitcnt -= 8; \
  789. } \
  790. }
  791. for (i=0; i<size; i++)
  792. {
  793. if (from[i])
  794. {
  795. _BIT(1,1);
  796. _BIT(from[i],8);
  797. }
  798. else
  799. _BIT(0,1);
  800. }
  801. _FLUSH;
  802. return off;
  803. }
  804. #endif /* !UTIL */
  805. #endif /* ndef VMS_PK_EXTRA */
  806. #endif /* VMS */