home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / zip21.zip / vms / vms_pk.c < prev    next >
C/C++ Source or Header  |  1996-04-01  |  12KB  |  415 lines

  1. /*************************************************************************
  2.  *                                                                       *
  3.  * 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 unmodified, and that this copyright notice is retained.  *
  7.  *                                                                       *
  8.  *************************************************************************/
  9.  
  10. /*
  11.  *    vms_pk.c  by Igor Mandrichenko
  12.  *
  13.  *    version 2.0       20-mar-1993
  14.  *                      Generates PKWARE version of VMS attributes
  15.  *                      extra field according to appnote 2.0.
  16.  *                      Uses low level QIO-ACP interface.
  17.  *    version 2.0-1     10-apr-1993
  18.  *                      Save ACLs
  19.  *    version 2.1       24-aug-1993
  20.  *                      By default produce 0x010C extra record ID instead of
  21.  *                      PKWARE's 0x000C. The format is mostly compatible with
  22.  *                      PKWARE.
  23.  *                      Incompatibility (?): zip produces multiple ACE
  24.  *                      fields.
  25.  *    version 2.1-1     Clean extra fields in vms_get_attributes().
  26.  *                      Fixed bug with EOF.
  27.  *    version 2.1-2     15-sep-1995, Chr. Spieler
  28.  *                      Removed extra fields cleanup from vms_get_attributes().
  29.  *                      This is now done in zipup.c
  30.  *                      Modified (according to UnZip's vms.[ch]) the fib stuff
  31.  *                      for DEC C (AXP,VAX) support.
  32.  *    version 2.2       28-sep-1995, Chr. Spieler
  33.  *                      Reorganized code for easier maintance of the two
  34.  *                      incompatible flavours (IM style and PK style) VMS
  35.  *                      attribute support.  Generic functions (common to
  36.  *                      both flavours) are now collected in a `wrapper'
  37.  *                      source file that includes one of the VMS attribute
  38.  *                      handlers.
  39.  *                      Made extra block header conforming to PKware's
  40.  *                      specification (extra block header has a length
  41.  *                      of four bytes, two bytes for a signature, and two
  42.  *                      bytes for the length of the block excluding this
  43.  *                      header.
  44.  *    version 2.2-1     19-oct-1995, Chr. Spieler
  45.  *                      Fixed bug in CRC calculation.
  46.  *                      Use official PK VMS extra field id.
  47.  */
  48.  
  49. #ifdef VMS                      /* For VMS only ! */
  50.  
  51.  
  52. #ifndef __SSDEF_LOADED
  53. #include <ssdef.h>
  54. #endif
  55.  
  56. #ifndef VMS_ZIP
  57. #define VMS_ZIP
  58. #endif
  59. #include "vms/vms.h"
  60. #include "vms/vmsdefs.h"
  61.  
  62. #ifndef ERR
  63. #define ERR(x) (((x)&1)==0)
  64. #endif
  65.  
  66. #ifndef NULL
  67. #define NULL (void*)(0L)
  68. #endif
  69.  
  70. #ifndef UTIL
  71.  
  72. static struct PK_info PK_def_info =
  73. {
  74.         ATR$C_RECATTR,  ATR$S_RECATTR,  {0},
  75.         ATR$C_UCHAR,    ATR$S_UCHAR,    {0},
  76.         ATR$C_CREDATE,  ATR$S_CREDATE,  {0},
  77.         ATR$C_REVDATE,  ATR$S_REVDATE,  {0},
  78.         ATR$C_EXPDATE,  ATR$S_EXPDATE,  {0},
  79.         ATR$C_BAKDATE,  ATR$S_BAKDATE,  {0},
  80.         ATR$C_ASCDATES, sizeof(ush),    0,
  81.         ATR$C_UIC,      ATR$S_UIC,      {0},
  82.         ATR$C_FPRO,     ATR$S_FPRO,     {0},
  83.         ATR$C_RPRO,     ATR$S_RPRO,     {0},
  84.         ATR$C_JOURNAL,  ATR$S_JOURNAL,  {0}
  85. };
  86.  
  87. /* Forward declarations of public functions: */
  88. struct ioctx *vms_open(char *file, char *how);
  89. int  vms_read(register struct ioctx *ctx,
  90.               register char *buf, register int size);
  91. int  vms_error(struct ioctx *ctx);
  92. int  vms_rewind(struct ioctx *ctx);
  93. void vms_get_attributes(struct ioctx *ctx, struct zlist far *z);
  94. int  vms_close(struct ioctx *ctx);
  95.  
  96. /*---------------*
  97.  |  vms_open()   |
  98.  *---------------*
  99.  |  This routine opens file for reading fetching its attributes.
  100.  |  Returns pointer to file description structure.
  101.  */
  102.  
  103. struct ioctx *vms_open(file,how)
  104. char *file,*how;
  105. {
  106.     static struct atrdef        Atr[VMS_MAX_ATRCNT+1];
  107.     static struct NAM           Nam;
  108.     static struct fibdef        Fib;
  109.     static struct dsc$descriptor FibDesc =
  110.         {sizeof(Fib),DSC$K_DTYPE_Z,DSC$K_CLASS_S,(char *)&Fib};
  111.     static struct dsc$descriptor_s DevDesc =
  112.         {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,&Nam.nam$t_dvi[1]};
  113.     static struct dsc$descriptor_s FileName =
  114.         {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
  115.     static char EName[NAM$C_MAXRSS];
  116.     static char RName[NAM$C_MAXRSS];
  117.  
  118.     struct FAB  Fab;
  119.     register struct ioctx *ctx;
  120.     register struct fatdef *fat;
  121.     int status;
  122.     int i;
  123.     ulg efblk,hiblk;
  124.  
  125.     if( (ctx=(struct ioctx *)malloc(sizeof(struct ioctx))) == NULL )
  126.         return NULL;
  127.     ctx -> PKi = PK_def_info;
  128.  
  129. #define FILL_REQ(ix,id,b)   {       \
  130.     Atr[ix].atr$l_addr = &(b);      \
  131.     Atr[ix].atr$w_type = (id);      \
  132.     Atr[ix].atr$w_size = sizeof(b); \
  133. }
  134.     FILL_REQ(0, ATR$C_RECATTR,  ctx->PKi.ra);
  135.     FILL_REQ(1, ATR$C_UCHAR,    ctx->PKi.uc);
  136.     FILL_REQ(2, ATR$C_REVDATE,  ctx->PKi.rd);
  137.     FILL_REQ(3, ATR$C_EXPDATE,  ctx->PKi.ed);
  138.     FILL_REQ(4, ATR$C_CREDATE,  ctx->PKi.cd);
  139.     FILL_REQ(5, ATR$C_BAKDATE,  ctx->PKi.bd);
  140.     FILL_REQ(6, ATR$C_ASCDATES, ctx->PKi.rn);
  141.     FILL_REQ(7, ATR$C_JOURNAL,  ctx->PKi.jr);
  142.     FILL_REQ(8, ATR$C_RPRO,     ctx->PKi.rp);
  143.     FILL_REQ(9, ATR$C_FPRO,     ctx->PKi.fp);
  144.     FILL_REQ(10,ATR$C_UIC,      ctx->PKi.ui);
  145.     FILL_REQ(11,ATR$C_ACLLENGTH,ctx->acllen);
  146.     FILL_REQ(12,ATR$C_READACL,  ctx->aclbuf);
  147.  
  148.     Atr[13].atr$w_type = 0;     /* End of ATR list */
  149.     Atr[13].atr$w_size = 0;
  150.     Atr[13].atr$l_addr = (byte *)NULL;
  151.  
  152.     /* initialize RMS structures, we need a NAM to retrieve the FID */
  153.     Fab = cc$rms_fab;
  154.     Fab.fab$l_fna = file ; /* name of file */
  155.     Fab.fab$b_fns = strlen(file);
  156.     Fab.fab$l_nam = &Nam; /* FAB has an associated NAM */
  157.     Nam = cc$rms_nam;
  158.     Nam.nam$l_esa = EName; /* expanded filename */
  159.     Nam.nam$b_ess = sizeof(EName);
  160.     Nam.nam$l_rsa = RName; /* resultant filename */
  161.     Nam.nam$b_rss = sizeof(RName);
  162.  
  163.     /* do $PARSE and $SEARCH here */
  164.     status = sys$parse(&Fab);
  165.     if (!(status & 1)) return NULL;
  166.  
  167.     /* search for the first file.. If none signal error */
  168.     status = sys$search(&Fab);
  169.     if (!(status & 1)) return NULL;
  170.  
  171.     /* initialize Device name length, note that this points into the NAM
  172.          to get the device name filled in by the $PARSE, $SEARCH services */
  173.     DevDesc.dsc$w_length = Nam.nam$t_dvi[0];
  174.  
  175.     status = sys$assign(&DevDesc,&ctx->chan,0,0);
  176.     if (!(status & 1)) return NULL;
  177.  
  178.     FileName.dsc$a_pointer = Nam.nam$l_name;
  179.     FileName.dsc$w_length = Nam.nam$b_name+Nam.nam$b_type+Nam.nam$b_ver;
  180.  
  181.     /* Initialize the FIB */
  182.     Fib.FIB$L_ACCTL = FIB$M_NOWRITE;
  183.     for (i=0;i<3;i++)
  184.         Fib.FIB$W_FID[i]=Nam.nam$w_fid[i];
  185.     for (i=0;i<3;i++)
  186.         Fib.FIB$W_DID[i]=Nam.nam$w_did[i];
  187.  
  188.     /* Use the IO$_ACCESS function to return info about the file */
  189.     status = sys$qiow(0,ctx->chan,IO$_ACCESS|IO$M_ACCESS,&ctx->iosb,0,0,
  190.                     &FibDesc,&FileName,0,0,&Atr,0);
  191.  
  192.     if (ERR(status) || ERR(status = ctx->iosb.status))
  193.     {
  194.         vms_close(ctx);
  195.         return NULL;
  196.     }
  197.  
  198.     fat = (struct fatdef *)&(ctx -> PKi.ra);
  199.  
  200. #define SWAPW(x)        ( (((x)>>16)&0xFFFF) + ((x)<<16) )
  201.  
  202.     efblk = SWAPW(fat->fat$l_efblk);
  203.     hiblk = SWAPW(fat->fat$l_hiblk);
  204.  
  205.     if( efblk == 0 && fat -> fat$w_ffbyte == 0 )
  206.         ctx -> size =
  207.         ctx -> rest = hiblk * 512;
  208.     else
  209.         ctx -> size =
  210.         ctx -> rest = (efblk - 1) * 512 + fat -> fat$w_ffbyte;
  211.  
  212.     ctx -> status = SS$_NORMAL;
  213.     ctx -> vbn = 1;
  214.     return ctx;
  215. }
  216.  
  217. #define KByte 1024
  218.  
  219. /*----------------*
  220.  |   vms_read()   |
  221.  *----------------*
  222.  |   Reads file block by block into the buffer.
  223.  |   Stops on EOF, returns number of bytes actually read.
  224.  |   Note: size of the buffer must be greater than or equal to 512 !
  225.  */
  226.  
  227. int vms_read(ctx, buf, size)
  228. register struct ioctx *ctx;
  229. register char *buf;
  230. register int size;
  231. {
  232.     int status;
  233.     long nr=0;
  234.  
  235.     if (ctx -> rest <= 0 || ctx -> status == SS$_ENDOFFILE)
  236.         return 0;               /* Eof */
  237.  
  238.     if(size <= 0)
  239.         return 0;
  240.  
  241.     if(size > 16*KByte)
  242.         size = 16*KByte;
  243.     else if(size > 512)
  244.         size &= ~511L;          /* Round to integer number of blocks */
  245.  
  246.     do
  247.     {
  248.         status = sys$qiow(0, ctx->chan, IO$_READVBLK,
  249.             &ctx->iosb, 0, 0,
  250.             buf, size, ctx->vbn,0,0,0);
  251.  
  252.         ctx->vbn += size>>9;
  253.         if( size < 512 )
  254.                 ++ctx->vbn;
  255.  
  256.         if( !ERR(status) )
  257.                 status = ctx->iosb.status;
  258.  
  259.         if( !ERR(status) || status == SS$_ENDOFFILE )
  260.         {
  261.             register int count;
  262.  
  263.             if( status == SS$_ENDOFFILE )
  264.                 count = ctx->rest;
  265.             else
  266.                 count = ctx->iosb.count;
  267.  
  268.             size -= count;
  269.             buf  += count;
  270.             nr   += count;
  271.         }
  272.     } while( !ERR(status) && size > 0 );
  273.  
  274.     if (!ERR(status))
  275.     {
  276.         ctx -> status = SS$_NORMAL;
  277.         ctx -> rest -= nr;
  278.     }
  279.     else if(status == SS$_ENDOFFILE)
  280.     {
  281.         ctx -> status = SS$_ENDOFFILE;
  282.         ctx -> rest = 0;
  283.     }
  284.     else
  285.     {
  286.         ctx -> status = status;
  287.         ctx -> rest -= nr;
  288.     }
  289.     return nr;
  290. }
  291.  
  292. /*-----------------*
  293.  |   vms_error()   |
  294.  *-----------------*
  295.  |   Returns whether last operation on the file caused an error
  296.  */
  297.  
  298. int vms_error(ctx)
  299. struct ioctx *ctx;
  300. {   /* EOF is not actual error */
  301.     return ERR(ctx->status) && (ctx->status != SS$_ENDOFFILE);
  302. }
  303.  
  304. /*------------------*
  305.  |   vms_rewind()   |
  306.  *------------------*
  307.  |   Rewinds file to the beginning for the next vms_read().
  308.  */
  309.  
  310. int vms_rewind(ctx)
  311. struct ioctx *ctx;
  312. {
  313.     ctx -> vbn = 1;
  314.     ctx -> rest = ctx -> size;
  315.     return 0;
  316. }
  317.  
  318. /*--------------------------*
  319.  |   vms_get_attributes()   |
  320.  *--------------------------*
  321.  |   Returns pointer to malloc'ed PKWARE extra field with file attributes.
  322.  |   File must be open already by vms_open()
  323.  */
  324.  
  325. void vms_get_attributes(ctx,z,z_utim)
  326. struct ioctx *ctx;
  327. struct zlist far *z;    /* zip entry to compress */
  328. ztimbuf *z_utim;
  329. {
  330.     byte    *p,*b;
  331.     struct  PK_header    *h;
  332.     int     l;
  333.  
  334.     if( !vms_native )
  335.     {
  336. #ifdef USE_EF_UX_TIME
  337.         /*
  338.          *  A `portable' zipfile entry is created. Create an "UX" extra block
  339.          *  containing UNIX style time stamps, which helps maintaining the
  340.          *  `real' "last modified" time when the archive is tranported
  341.          *  across time zone boundaries.
  342.          */
  343.         if ((b = (uch *)malloc(EB_HEADSIZE+EB_UX_MINLEN)) == NULL)
  344.             return;
  345.  
  346.         b[0]  = 'U';
  347.         b[1]  = 'X';
  348.         b[2]  = EB_UX_MINLEN;          /* length of data part of e.f. */
  349.         b[3]  = 0;
  350.         b[4]  = (byte)(z_utim->actime);
  351.         b[5]  = (byte)(z_utim->actime >> 8);
  352.         b[6]  = (byte)(z_utim->actime >> 16);
  353.         b[7]  = (byte)(z_utim->actime >> 24);
  354.         b[8]  = (byte)(z_utim->modtime);
  355.         b[9]  = (byte)(z_utim->modtime >> 8);
  356.         b[10] = (byte)(z_utim->modtime >> 16);
  357.         b[11] = (byte)(z_utim->modtime >> 24);
  358.  
  359.         z->cext = z->ext = (EB_HEADSIZE+EB_UX_MINLEN);
  360.         z->cextra = z->extra = (char*)b;
  361. #endif /* USE_EF_UX_TIME */
  362.  
  363.         return;
  364.     }
  365.  
  366.     l = PK_HEADER_SIZE+sizeof(ctx->PKi);
  367.     if(ctx->acllen > 0)
  368.         l += PK_FLDHDR_SIZE + ctx->acllen;
  369.  
  370.     b = (uch *)malloc(l);
  371.     if( b==NULL )
  372.         return;
  373.  
  374.     h = (struct PK_header *)b;
  375.     h->tag = PK_SIGNATURE;
  376.     h->size = l - EB_HEADSIZE;
  377.     p = (h->data);
  378.  
  379.     /* Copy default set of attributes */
  380.     memcpy(h->data,(uch*)&(ctx->PKi),sizeof(ctx->PKi));
  381.     p += sizeof(ctx->PKi);
  382.  
  383.     if( ctx->acllen > 0 )
  384.     {
  385.         struct PK_field *f;
  386.  
  387.         if(dosify)
  388.             zipwarn("file has ACL, may be incompatible with PKUNZIP","");
  389.  
  390.         f = (struct PK_field *)p;
  391.         f->tag = ATR$C_ADDACLENT;
  392.         f->size = ctx->acllen;
  393.         memcpy((char *)&(f->value[0]),ctx->aclbuf,ctx->acllen);
  394.         p += PK_FLDHDR_SIZE + ctx->acllen;
  395.     }
  396.  
  397.  
  398.     h->crc32 = crc32(0L, (uch *)NULL, 0);   /* Init CRC register */
  399.     h->crc32 = crc32(h->crc32, (uch *)(h->data), l - PK_HEADER_SIZE);
  400.  
  401.     z->ext = z->cext = l;
  402.     z->extra = z->cextra = (char *)b;
  403. }
  404.  
  405. int vms_close(ctx)
  406. struct ioctx *ctx;
  407. {
  408.         sys$dassgn(ctx->chan);
  409.         free(ctx);
  410.         return 0;
  411. }
  412.  
  413. #endif /* !_UTIL */
  414. #endif /* VMS */
  415.