home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / zip201.zip / vms / vms.c < prev    next >
C/C++ Source or Header  |  1993-09-10  |  21KB  |  830 lines

  1. /*************************************************************************
  2.  *                                                                       *
  3.  * VMS portions copyright (C) 1993 Igor Mandrichenko.                    *
  4.  * Permission is granted to any individual or institution to use, copy,  *
  5.  * or redistribute this software so long as all of the original files    *
  6.  * are included, that it is not sold for profit, and that this copyright *
  7.  * notice is retained.                                                   *
  8.  *                                                                       *
  9.  *************************************************************************/
  10.  
  11. /*
  12.  *  vms.c (zip) by Igor Mandrichenko    Version 2.2-2
  13.  *
  14.  *  Revision history:
  15.  *  ...
  16.  *  2.1-1       16-feb-1993     I.Mandrichenko  
  17.  *      Get file size from XABFHC and check bytes rest in file before
  18.  *      reading. 
  19.  *  2.1-2       2-mar-1993      I.Mandrichenko
  20.  *      Make code more standard
  21.  *  2.2         21-jun-1993     I.Mandrichenko
  22.  *      Free all allocated space, use more static storage.
  23.  *      Use memcompress() from bits.c (deflation) for block compression.
  24.  *      To revert to old compression method #define OLD_COMPRESS
  25.  *  2.2-2       18-jan-1993     I.Mandrichenko
  26.  *      vms_stat() added - version of stat() that handles special
  27.  *      case when end-of-file-block == 0
  28.  */
  29.  
  30. #ifdef VMS                      /* For VMS only ! */
  31.  
  32. #define OLD_COMPRESS    /*To use old compression method define it.*/
  33.  
  34. #include <rms.h>
  35. #include <descrip.h>
  36. #include <syidef.h>
  37. #include <stat.h>
  38.  
  39. #ifndef VAXC
  40.                                 /* This definition may be missed */
  41. struct XAB {
  42.     unsigned char xab$b_cod;
  43.     unsigned char xab$b_bln;
  44.     short int xabdef$$_fill_1;
  45.     char *xab$l_nxt;
  46. };
  47.  
  48. #endif
  49.  
  50. #ifndef SYI$_VERSION
  51. #define SYI$_VERSION 4096       /* VMS 5.4 definition */
  52. #endif
  53.  
  54. #define UTIL            /* do not declare the read_buf variable */
  55.  
  56. #include "zip.h"
  57.  
  58. #define ERR(s)  !((s)&1)
  59.  
  60. #define RET_ERROR 1
  61. #define RET_SUCCESS 0
  62. #define RET_EOF 0
  63.  
  64. #define Kbyte 1024
  65.  
  66. typedef struct XAB *xabptr;
  67.  
  68. /*
  69. *   Extra record format
  70. *   ===================
  71. *   signature       (2 bytes)   = 'I','M'
  72. *   size            (2 bytes)
  73. *   block signature (4 bytes)
  74. *   flags           (2 butes)
  75. *   uncomprssed size(2 bytes)
  76. *   reserved        (4 bytes)
  77. *   data            (size-12 bytes)
  78. *   ....
  79. */
  80.  
  81.  
  82. /*
  83. *   Extra field signature and block signatures
  84. */
  85. #define SIGNATURE "IM"
  86. #define EXTBSL  4               /* Block signature length   */
  87. #define RESL    8
  88.  
  89. #define BC_MASK         07      /* 3 bits for compression type */       
  90. #define BC_STORED       0       /* Stored */
  91. #define BC_00           1       /* 0byte -> 0bit compression */
  92. #define BC_DEFL         2       /* Deflated */
  93.  
  94. struct extra_block
  95. {       ush     im_sig;
  96.         ush     size;
  97.         ulg     block_sig;
  98.         ush     flags;
  99.         ush     length;
  100.         ulg     reserved;
  101.         uch     body[1];        /* The actual size is unknown */
  102. };
  103.  
  104. #define FABSIG  "VFAB"
  105. #define XALLSIG "VALL"
  106. #define XFHCSIG "VFHC"
  107. #define XDATSIG "VDAT"
  108. #define XRDTSIG "VRDT"
  109. #define XPROSIG "VPRO"
  110. #define XKEYSIG "VKEY"
  111. #define VERSIG  "VMSV"
  112. /*
  113. *   Block sizes
  114. */
  115. #define FABL    (cc$rms_fab.fab$b_bln)
  116. #define RABL    (cc$rms_rab.rab$b_bln)
  117. #define XALLL   (cc$rms_xaball.xab$b_bln)
  118. #define XDATL   (cc$rms_xabdat.xab$b_bln)
  119. #define XFHCL   (cc$rms_xabfhc.xab$b_bln)
  120. #define XKEYL   (cc$rms_xabkey.xab$b_bln)
  121. #define XPROL   (cc$rms_xabpro.xab$b_bln)
  122. #define XRDTL   (cc$rms_xabrdt.xab$b_bln)
  123. #define XSUML   (cc$rms_xabsum.xab$b_bln)
  124. #define EXTHL   (4+EXTBSL+RESL)
  125. #define EXTL0   ((FABL + EXTHL)+        \
  126.                 (XFHCL + EXTHL)+        \
  127.                 (XPROL + EXTHL)+        \
  128.                 (XDATL + EXTHL)+        \
  129.                 (XRDTL + EXTHL))
  130.  
  131. #ifdef OLD_COMPRESS
  132. #define PAD     sizeof(uch)
  133. #else
  134. #define PAD     10*sizeof(ush)          /* Two extra bytes for compr. header */
  135. #endif
  136.  
  137. #define PAD0    (5*PAD)                 /* Reserve space for the case when
  138.                                         *  compression fails */
  139. static int _compress();
  140.  
  141. /*******************************
  142.  *   Function get_attributes   *
  143.  *******************************/
  144.  
  145. static uch *_compress_block();
  146. static int get_vms_version();
  147.  
  148. int set_extra_field(z)
  149.   struct zlist *z;
  150. /*
  151.  *      Get file VMS file attributes and store them into extent fields.
  152.  *      Store VMS version also.
  153.  *      On error leave z intact.
  154.  */
  155. {
  156.     int status;
  157.     uch *extra=(uch*)NULL, *scan;
  158.     extent extra_l;
  159.     static struct FAB fab;
  160.     static struct XABSUM xabsum;
  161.     static struct XABFHC xabfhc;
  162.     static struct XABDAT xabdat;
  163.     static struct XABPRO xabpro;
  164.     static struct XABRDT xabrdt;
  165.     xabptr x = (xabptr)NULL, xab_chain = (xabptr)NULL, last_xab = (xabptr)NULL;
  166.     int nk, na;
  167.     int i;
  168.     int rc=RET_ERROR;
  169.     char verbuf[80];
  170.     int verlen = 0;
  171.  
  172.     if (!vms_native) return 0;
  173.  
  174.     /*
  175.     *   Initialize RMS control blocks and link them
  176.     */
  177.  
  178.     fab =    cc$rms_fab;
  179.     xabsum = cc$rms_xabsum;
  180.     xabdat = cc$rms_xabdat;
  181.     xabfhc = cc$rms_xabfhc;
  182.     xabpro = cc$rms_xabpro;
  183.     xabrdt = cc$rms_xabrdt;
  184.  
  185.  
  186.     fab.fab$l_xab = (char*)&xabsum;
  187.     /*
  188.     *   Open the file and read summary information.
  189.     */
  190.     fab.fab$b_fns = strlen(z->name);
  191.     fab.fab$l_fna = z->name;
  192.  
  193.     status = sys$open(&fab);
  194.     if (ERR(status))
  195.     {
  196. #ifdef DEBUG
  197.         printf("set_extra_field: sys$open for file %s:\n  error status = %d\n",
  198.                z->name, status);
  199. #endif
  200.         goto err_exit;
  201.     }
  202.  
  203.     nk = xabsum.xab$b_nok;
  204.     na = xabsum.xab$b_noa;
  205. #ifdef DEBUG
  206.     printf("%d keys, %d alls\n", nk, na);
  207. #endif
  208.  
  209.     /*
  210.     *   Allocate XABKEY and XABALL blocks ind link them
  211.     */
  212.  
  213.     xabfhc.xab$l_nxt = (char*)&xabdat;
  214.     xabdat.xab$l_nxt = (char*)&xabpro;
  215.     xabpro.xab$l_nxt = (char*)&xabrdt;
  216.     xabrdt.xab$l_nxt = (char*)0L;
  217.  
  218.     xab_chain = (xabptr)(&xabfhc);
  219.     last_xab  = (xabptr)(&xabrdt);
  220.  
  221. #define INIT(ptr,size,init)     \
  222.         if( (ptr = (uch*)malloc(size)) == NULL )        \
  223.         {                                               \
  224.               printf( "set_extra_field: Insufficient memory.\n" );   \
  225.                       goto err_exit;                    \
  226.         }                                               \
  227.         *(ptr) = (init);
  228.     /*
  229.     *   Allocate and initialize all needed XABKEYs and XABALLs
  230.     */
  231.     for (i = 0; i < nk; i++)
  232.     {
  233.         struct XABKEY *k;
  234.         INIT(k, XKEYL, cc$rms_xabkey);
  235.         k->xab$b_ref = i;
  236.         if (last_xab != 0L)
  237.             last_xab->xab$l_nxt = (char*)k;
  238.         last_xab = (xabptr)k;
  239.     }
  240.     for (i = 0; i < na; i++)
  241.     {
  242.         struct XABALL *a;
  243.         INIT(a, XALLL, cc$rms_xaball);
  244.         a->xab$b_aid = i;
  245.         if (last_xab != 0L)
  246.             last_xab->xab$l_nxt = (char*)a;
  247.         last_xab = (xabptr)a;
  248.     }
  249.  
  250.     fab.fab$l_xab = (char*)xab_chain;
  251. #ifdef DEBUG
  252.     printf("Dump of XAB chain before DISPLAY:\n");
  253.     for (x = xab_chain; x != 0L; x = x->xab$l_nxt)
  254.         dump_rms_block(x);
  255. #endif
  256.     /*
  257.     *   Get information on the file structure etc.
  258.     */
  259.     status = sys$display(&fab, 0, 0);
  260.     if (ERR(status))
  261.     {
  262. #ifdef DEBUG
  263.         printf("set_extra_field: sys$display for file %s:\n  error status = %d\n",
  264.                z->name, status);
  265. #endif
  266.         goto err_exit;
  267.     }
  268.  
  269. #ifdef DEBUG
  270.     printf("\nDump of XAB chain after DISPLAY:\n");
  271.     for (x = xab_chain; x != 0L; x = x->xab$l_nxt)
  272.         dump_rms_block(x);
  273. #endif
  274.  
  275.     fab.fab$l_xab = 0;  /* Keep XABs */
  276.     status = sys$close(&fab);
  277.     if (ERR(status))
  278.     {
  279. #ifdef DEBUG
  280.         printf("set_extra_field: sys$close for file %s:\n  error status = %d\n",
  281.                z->name, status);
  282. #endif
  283.         goto err_exit;
  284.     }
  285.  
  286.     extra_l = EXTL0 + nk * (XKEYL + EXTHL) + na * (XALLL + EXTHL);
  287. #ifndef OLD_COMPRESS
  288.     extra_l += PAD0 + (nk+na) * PAD;
  289. #endif
  290.  
  291.     if( verlen = get_vms_version(verbuf,sizeof(verbuf)) )
  292.     {   extra_l += verlen + EXTHL;
  293. #ifndef OLD_COMPRESS
  294.         extra_l += PAD;
  295. #endif
  296.     }
  297.  
  298.     if ((scan = extra = (uch *) malloc(extra_l)) == (uch*)NULL)
  299.     {
  300. #ifdef DEBUG
  301.         printf("set_extra_field: Insufficient memory to allocate extra buffer\n");
  302. #endif
  303.         goto err_exit;
  304.     }
  305.  
  306.  
  307.     if( verlen > 0 )
  308.         scan = _compress_block(scan,verbuf, verlen, VERSIG);
  309.  
  310.     /*
  311.      *  Zero all unusable fields to improve compression
  312.      */
  313.     fab.fab$b_fns = fab.fab$b_shr = fab.fab$b_dns = fab.fab$b_fac = 0;
  314.     fab.fab$w_ifi = 0;
  315.     fab.fab$l_stv = fab.fab$l_sts = fab.fab$l_ctx = 0;
  316.     fab.fab$l_fna = fab.fab$l_nam = fab.fab$l_xab = fab.fab$l_dna = (char*)0L;
  317.  
  318. #ifdef DEBUG
  319.     dump_rms_block( &fab );
  320. #endif
  321.     scan = _compress_block(scan,&fab, FABL, FABSIG);
  322.     for (x = xab_chain; x != 0L;)
  323.     {
  324.         int bln;
  325.         char *sig;
  326.         xabptr next;
  327.  
  328.         next = (xabptr)(x->xab$l_nxt);
  329.         x->xab$l_nxt = 0;
  330.  
  331.         switch (x->xab$b_cod)
  332.         {
  333.             case XAB$C_ALL:
  334.                 bln = XALLL;
  335.                 sig = XALLSIG;
  336.                 break;
  337.             case XAB$C_KEY:
  338.                 bln = XKEYL;
  339.                 sig = XKEYSIG;
  340.                 break;
  341.             case XAB$C_PRO:
  342.                 bln = XPROL;
  343.                 sig = XPROSIG;
  344.                 break;
  345.             case XAB$C_FHC:
  346.                 bln = XFHCL;
  347.                 sig = XFHCSIG;
  348.                 break;
  349.             case XAB$C_DAT:
  350.                 bln = XDATL;
  351.                 sig = XDATSIG;
  352.                 break;
  353.             case XAB$C_RDT:
  354.                 bln = XRDTL;
  355.                 sig = XRDTSIG;
  356.                 break;
  357.             default:
  358.                 bln = 0;
  359.                 sig = 0L;
  360.                 break;
  361.         }
  362.         if (bln > 0)
  363.             scan = _compress_block(scan,x, bln, sig);
  364.         x = next;
  365.     }
  366.  
  367.     z->ext = z->cext = scan-extra;
  368.     z->extra = z->cextra = (char*)extra;
  369.     rc = RET_SUCCESS;
  370.  
  371. err_exit:
  372.     /*
  373.     * Give up all allocated blocks
  374.     */
  375.     for(x = (struct XAB *)xab_chain; x != 0L; )
  376.     {   struct XAB *next;
  377.         next = (xabptr)(x->xab$l_nxt);
  378.         if( x->xab$b_cod == XAB$C_ALL || x->xab$b_cod == XAB$C_KEY )
  379.                 free(x);
  380.         x = next;
  381.     }
  382.     return rc;
  383. }
  384.  
  385. static int get_vms_version(verbuf,len)
  386. char *verbuf;
  387. int len;
  388. {   int i = SYI$_VERSION;
  389.     int verlen = 0;
  390.     struct dsc$descriptor version;
  391.     char *m;
  392.  
  393.     version.dsc$a_pointer = verbuf;
  394.     version.dsc$w_length  = len-1;
  395.     version.dsc$b_dtype   = DSC$K_DTYPE_B;
  396.     version.dsc$b_class   = DSC$K_CLASS_S;
  397.  
  398.     if (ERR(lib$getsyi(&i, 0, &version, &verlen, 0, 0)) || verlen == 0)
  399.         return 0;
  400.  
  401.     /* Cut out trailing spaces "V5.4-3   " -> "V5.4-3" */
  402.     for(m=verbuf+verlen,i=verlen-1; i>0 && verbuf[i]==' '; --i) 
  403.         --m;
  404.     *m = 0;
  405.  
  406.     /* Cut out release number "V5.4-3" -> "V5.4" */
  407.     if( (m=strrchr(verbuf,'-')) != (char*)NULL )
  408.         *m = 0;
  409.     return strlen(verbuf)+1;    /* Transmit ending 0 too */
  410. }
  411.  
  412. #define CTXSIG ((ulg)('CtXx'))
  413.  
  414. typedef struct user_context
  415. {
  416.     ulg sig;
  417.     struct FAB *fab;
  418.     struct RAB *rab;
  419.     ulg size,rest;
  420.     int status;
  421. } Ctx, *Ctxptr;
  422.  
  423. Ctx init_ctx =  
  424. {       CTXSIG,
  425.         0L,
  426.         0L,
  427.         0L,
  428.         0L,
  429.         0
  430. };
  431.  
  432. #define CTXL    sizeof(Ctx)
  433. #define CHECK_RAB(_r) ( (_r) != 0 &&                            \
  434.                         (_r) -> rab$b_bid == RAB$C_BID &&       \
  435.                         (_r) -> rab$b_bln == RAB$C_BLN &&       \
  436.                         (_r) -> rab$l_ctx != 0L     &&          \
  437.                         (_r) -> rab$l_fab != 0L )
  438.  
  439. /**************************
  440.  *   Function vms_open    *
  441.  **************************/
  442. struct RAB *vms_open(name)
  443.     char *name;
  444. {
  445.     struct RAB *rab;
  446.     struct FAB *fab;
  447.     struct XABFHC *fhc;
  448.     Ctxptr ctx;
  449.  
  450.     if ((fab = (struct FAB *) malloc(FABL)) == (struct FAB *)NULL)
  451.         return 0;
  452.     if ((rab = (struct RAB *) malloc(RABL)) == (struct RAB *)NULL)
  453.     {
  454.         free(fab);
  455.         return 0;
  456.     }
  457.     if ((fhc = (struct XABFHC *) malloc(XFHCL)) == (struct XABFHC *)NULL)
  458.     {
  459.         free(rab);
  460.         free(fab);
  461.         return 0;
  462.     }
  463.     if ((ctx = (Ctxptr) malloc(CTXL)) == (Ctxptr)NULL)
  464.     {
  465.         free(fhc);
  466.         free(fab);
  467.         free(rab);
  468.         return 0;
  469.     }
  470.     *fab = cc$rms_fab;
  471.     *rab = cc$rms_rab;
  472.     *fhc = cc$rms_xabfhc;
  473.  
  474.     fab->fab$l_fna = name;
  475.     fab->fab$b_fns = strlen(name);
  476.     fab->fab$b_fac = FAB$M_GET | FAB$M_BIO;
  477.     fab->fab$l_xab = (char*)fhc;
  478.  
  479.     if (ERR(sys$open(fab)))
  480.     {
  481.         sys$close(fab);
  482.         free(fhc);
  483.         free(fab);
  484.         free(rab);
  485.         free(ctx);
  486.         return 0;
  487.     }
  488.  
  489.     rab->rab$l_fab = fab;
  490.     rab->rab$l_rop = RAB$M_BIO;
  491.  
  492.     if (ERR(sys$connect(rab)))
  493.     {
  494.         sys$close(fab);
  495.         free(fab);
  496.         free(rab);
  497.         free(ctx);
  498.         return 0;
  499.     }
  500.  
  501.     *ctx = init_ctx;
  502.     ctx->rab = rab;
  503.     ctx->fab = fab;
  504.  
  505.     if( fhc->xab$l_ebk > 0 )
  506.         ctx->size = ctx->rest = ( fhc->xab$l_ebk-1 ) * 512 + fhc->xab$w_ffb;
  507.     else if( fab->fab$b_org == FAB$C_IDX
  508.             || fab->fab$b_org == FAB$C_REL
  509.             || fab->fab$b_org == FAB$C_HSH )
  510.                 /* Special case, when ebk=0: save entire allocated space */
  511.         ctx->size = ctx->rest = fhc->xab$l_hbk * 512;
  512.     else
  513.         ctx->size = ctx->rest = fhc->xab$w_ffb;
  514.     
  515.     free(fhc);
  516.     fab -> fab$l_xab = 0;
  517.     rab->rab$l_ctx = (long)ctx;
  518.     return rab;
  519. }
  520.  
  521. /**************************
  522.  *   Function vms_close   *
  523.  **************************/
  524. int vms_close(rab)
  525.     struct RAB *rab;
  526. {
  527.     struct FAB *fab;
  528.     Ctxptr ctx;
  529.  
  530.     if (!CHECK_RAB(rab))
  531.         return RET_ERROR;
  532.     fab = (ctx = (Ctxptr)(rab->rab$l_ctx))->fab;
  533.     sys$close(fab);
  534.  
  535.     free(fab);
  536.     free(rab);
  537.     free(ctx);
  538.  
  539.     return RET_SUCCESS;
  540. }
  541.  
  542. /**************************
  543.  *   Function vms_rewind  *
  544.  **************************/
  545. int vms_rewind(rab)
  546.     struct RAB *rab;
  547. {
  548.     Ctxptr ctx;
  549.  
  550.     int status;
  551.     if (!CHECK_RAB(rab))
  552.         return RET_ERROR;
  553.  
  554.     ctx = (Ctxptr) (rab->rab$l_ctx);
  555.     if (ERR(status = sys$rewind(rab)))
  556.     {
  557.         ctx->status = status;
  558.         return RET_ERROR;
  559.     }
  560.  
  561.     ctx->status = 0;
  562.     ctx->rest = ctx->size;
  563.     
  564.     return RET_SUCCESS;
  565. }
  566.  
  567. /**************************
  568.  *   Function vms_read    *
  569.  **************************/
  570. int vms_read(rab, buf, size)
  571.     struct RAB *rab;
  572. char *buf;
  573. int size;
  574. /*
  575. *       size must be greater or equal to 512 !
  576. */
  577. {
  578.     int status;
  579.     Ctxptr ctx;
  580.  
  581.     ctx = (Ctxptr)rab->rab$l_ctx;
  582.  
  583.     if (!CHECK_RAB(rab))
  584.         return 0;
  585.  
  586.     if (ctx -> rest <= 0)
  587.         return 0;               /* Eof */
  588.  
  589.     if(size > 16*Kbyte)         /* RMS can not read too much */
  590.         size = 16*Kbyte;
  591.     else
  592.         size &= ~511L;
  593.  
  594.     rab->rab$l_ubf = buf;
  595.     rab->rab$w_usz = size;
  596.     status = sys$read(rab);
  597.     if (!ERR(status) && rab->rab$w_rsz > 0)
  598.     {
  599.         ctx -> status = 0;
  600.         ctx -> rest -= rab->rab$w_rsz;
  601.         return rab->rab$w_rsz;
  602.     }
  603.     else
  604.     {
  605.         ctx->status = (status==RMS$_EOF ? 0:status);
  606.         if(status == RMS$_EOF)
  607.                 ctx -> rest = 0L;
  608.         return 0;
  609.     }
  610. }
  611.  
  612. /**************************
  613.  *   Function vms_error   *
  614.  **************************/
  615. int vms_error(rab)
  616.     struct RAB *rab;
  617. {
  618.     if (!CHECK_RAB(rab))
  619.         return RET_ERROR;
  620.     return ((Ctxptr) (rab->rab$l_ctx))->status;
  621. }
  622.  
  623.  
  624. dump_rms_block(p)
  625.     unsigned char *p;
  626. {
  627.     unsigned char bid, len;
  628.     int err;
  629.     char *type;
  630.     char buf[132];
  631.     int i;
  632.  
  633.     err = 0;
  634.     bid = p[0];
  635.     len = p[1];
  636.     switch (bid)
  637.     {
  638.         case FAB$C_BID:
  639.             type = "FAB";
  640.             break;
  641.         case XAB$C_ALL:
  642.             type = "xabALL";
  643.             break;
  644.         case XAB$C_KEY:
  645.             type = "xabKEY";
  646.             break;
  647.         case XAB$C_DAT:
  648.             type = "xabDAT";
  649.             break;
  650.         case XAB$C_RDT:
  651.             type = "xabRDT";
  652.             break;
  653.         case XAB$C_FHC:
  654.             type = "xabFHC";
  655.             break;
  656.         case XAB$C_PRO:
  657.             type = "xabPRO";
  658.             break;
  659.         default:
  660.             type = "Unknown";
  661.             err = 1;
  662.             break;
  663.     }
  664.     printf("Block @%08X of type %s (%d).", p, type, bid);
  665.     if (err)
  666.     {
  667.         printf("\n");
  668.         return;
  669.     }
  670.     printf(" Size = %d\n", len);
  671.     printf(" Offset - Hex - Dec\n");
  672.     for (i = 0; i < len; i += 8)
  673.     {
  674.         int j;
  675.         printf("%3d - ", i);
  676.         for (j = 0; j < 8; j++)
  677.             if (i + j < len)
  678.                 printf("%02X ", p[i + j]);
  679.             else
  680.                 printf("   ");
  681.         printf(" - ");
  682.         for (j = 0; j < 8; j++)
  683.             if (i + j < len)
  684.                 printf("%03d ", p[i + j]);
  685.             else
  686.                 printf("    ");
  687.         printf("\n");
  688.     }
  689. }
  690.  
  691. #ifdef OLD_COMPRESS
  692. # define BC_METHOD      BC_00
  693. # define        COMP_BLK(to,tos,from,froms) _compress( from,to,froms )
  694. #else
  695. # define BC_METHOD      BC_DEFL
  696. # define        COMP_BLK(to,tos,from,froms) memcompress(to,tos,from,froms)
  697. #endif
  698.  
  699. static uch *_compress_block(to,from,size,sig)
  700. register struct extra_block *to;
  701. uch *from,*sig;
  702. int size;
  703. {                               
  704.         ulg cl;
  705.         to -> im_sig =  *(ush*)SIGNATURE;
  706.         to -> block_sig =       *(ulg*)(sig);
  707.         to -> flags =           BC_METHOD;
  708.         to -> length =  size;
  709. #ifdef DEBUG
  710.         printf("\nmemcompr(%d,%d,%d,%d)\n",&(to->body[0]),size+PAD,from,size);
  711. #endif
  712.         cl = COMP_BLK( &(to->body[0]), size+PAD, from, size );
  713. #ifdef DEBUG
  714.         printf("Compressed to %d\n",cl);
  715. #endif
  716.         if( cl >= size )
  717.         {       memcpy(&(to->body[0]), from, size);
  718.                 to->flags = BC_STORED;
  719.                 cl = size;
  720. #ifdef DEBUG
  721.                 printf("Storing block...\n");
  722. #endif
  723.         }
  724.         return (uch*)(to) + (to->size = cl + EXTBSL + RESL) + 4;
  725. }
  726.  
  727. #define NBITS 32
  728.  
  729. static int _compress(from,to,size)
  730. uch *from,*to;
  731. int size;
  732. {
  733.     int off=0;
  734.     ulg bitbuf=0;
  735.     int bitcnt=0;
  736.     int i;
  737.  
  738. #define _BIT(val,len)   {                       \
  739.         if(bitcnt + (len) > NBITS)              \
  740.             while(bitcnt >= 8)                  \
  741.             {                                   \
  742.                 to[off++] = (uch)bitbuf;        \
  743.                 bitbuf >>= 8;                   \
  744.                 bitcnt -= 8;                    \
  745.             }                                   \
  746.         bitbuf |= ((ulg)(val))<<bitcnt;         \
  747.         bitcnt += len;                          \
  748.     }
  749.  
  750. #define _FLUSH  {                               \
  751.             while(bitcnt>0)                     \
  752.             {                                   \
  753.                 to[off++] = (uch)bitbuf;        \
  754.                 bitbuf >>= 8;                   \
  755.                 bitcnt -= 8;                    \
  756.             }                                   \
  757.         }
  758.  
  759.     for(i=0; i<size; i++)
  760.     {
  761.         if( from[i] )
  762.         {
  763.                 _BIT(1,1);
  764.                 _BIT(from[i],8);
  765.         }
  766.         else
  767.             _BIT(0,1);
  768.     }
  769.     _FLUSH;
  770.     return off;
  771. }
  772.  
  773. int vms_stat(file,s)
  774. char *file;
  775. struct stat *s;
  776. {   int status;
  777.     int staterr;
  778.     struct FAB fab;
  779.     struct XABFHC fhc;
  780.  
  781.     /*
  782.     *  In simplest case when stat() returns "ok" and file size is
  783.     *  nonzero or this is directory, finish with this
  784.     */
  785.  
  786.     if( (staterr=stat(file,s)) == 0     
  787.         && ( (int)(s->st_size) >= 0               /* Size - ok */
  788.              || (s->st_mode & S_IFREG) == 0       /* Not a plain file */
  789.            )
  790.     ) return staterr;
  791.  
  792.     /*
  793.     * Get here to handle the special case when stat() returns
  794.     * invalid file size. Use RMS to compute the size.
  795.     * When EOF block is zero, set file size to its physical size.
  796.     * One more case to get here is when this is remote file accessed
  797.     * via DECnet.
  798.     */
  799.  
  800.     fab = cc$rms_fab;
  801.     fhc = cc$rms_xabfhc;
  802.     fab.fab$l_fna = file;
  803.     fab.fab$b_fns = strlen(file);
  804.     fab.fab$l_xab = (char*)(&fhc);
  805.  
  806.     fab.fab$b_fac = FAB$M_GET;
  807.     
  808.     status = sys$open(&fab);
  809.     fab.fab$l_xab = (char*)0L;
  810.     sys$close(&fab);
  811.  
  812.     if( !ERR(status) )
  813.     {
  814.         if( fhc.xab$l_ebk > 0 )
  815.             s->st_size = ( fhc.xab$l_ebk-1 ) * 512 + fhc.xab$w_ffb;
  816.         else if( fab.fab$b_org == FAB$C_IDX
  817.                  || fab.fab$b_org == FAB$C_REL
  818.                  || fab.fab$b_org == FAB$C_HSH )
  819.                 /* Special case, when ebk=0: save entire allocated space */
  820.                     s->st_size = fhc.xab$l_hbk * 512;
  821.         else
  822.             s->st_size = fhc.xab$w_ffb;
  823.         return 0; /* stat() success code */
  824.     }
  825.     else
  826.         return status;
  827. }
  828.  
  829. #endif                          /* ?VMS */
  830.