home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / zip22.zip / vms / vms_pk.c < prev    next >
C/C++ Source or Header  |  1997-03-16  |  12KB  |  413 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.                         iztimes *z_utim);
  95. int  vms_close(struct ioctx *ctx);
  96.  
  97. /*---------------*
  98.  |  vms_open()   |
  99.  *---------------*
  100.  |  This routine opens file for reading fetching its attributes.
  101.  |  Returns pointer to file description structure.
  102.  */
  103.  
  104. struct ioctx *vms_open(file,how)
  105. char *file,*how;
  106. {
  107.     static struct atrdef        Atr[VMS_MAX_ATRCNT+1];
  108.     static struct NAM           Nam;
  109.     static struct fibdef        Fib;
  110.     static struct dsc$descriptor FibDesc =
  111.         {sizeof(Fib),DSC$K_DTYPE_Z,DSC$K_CLASS_S,(char *)&Fib};
  112.     static struct dsc$descriptor_s DevDesc =
  113.         {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,&Nam.nam$t_dvi[1]};
  114.     static struct dsc$descriptor_s FileName =
  115.         {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
  116.     static char EName[NAM$C_MAXRSS];
  117.     static char RName[NAM$C_MAXRSS];
  118.  
  119.     struct FAB  Fab;
  120.     register struct ioctx *ctx;
  121.     register struct fatdef *fat;
  122.     int status;
  123.     int i;
  124.     ulg efblk,hiblk;
  125.  
  126.     if( (ctx=(struct ioctx *)malloc(sizeof(struct ioctx))) == NULL )
  127.         return NULL;
  128.     ctx -> PKi = PK_def_info;
  129.  
  130. #define FILL_REQ(ix,id,b)   {       \
  131.     Atr[ix].atr$l_addr = &(b);      \
  132.     Atr[ix].atr$w_type = (id);      \
  133.     Atr[ix].atr$w_size = sizeof(b); \
  134. }
  135.     FILL_REQ(0, ATR$C_RECATTR,  ctx->PKi.ra);
  136.     FILL_REQ(1, ATR$C_UCHAR,    ctx->PKi.uc);
  137.     FILL_REQ(2, ATR$C_REVDATE,  ctx->PKi.rd);
  138.     FILL_REQ(3, ATR$C_EXPDATE,  ctx->PKi.ed);
  139.     FILL_REQ(4, ATR$C_CREDATE,  ctx->PKi.cd);
  140.     FILL_REQ(5, ATR$C_BAKDATE,  ctx->PKi.bd);
  141.     FILL_REQ(6, ATR$C_ASCDATES, ctx->PKi.rn);
  142.     FILL_REQ(7, ATR$C_JOURNAL,  ctx->PKi.jr);
  143.     FILL_REQ(8, ATR$C_RPRO,     ctx->PKi.rp);
  144.     FILL_REQ(9, ATR$C_FPRO,     ctx->PKi.fp);
  145.     FILL_REQ(10,ATR$C_UIC,      ctx->PKi.ui);
  146.     FILL_REQ(11,ATR$C_ACLLENGTH,ctx->acllen);
  147.     FILL_REQ(12,ATR$C_READACL,  ctx->aclbuf);
  148.  
  149.     Atr[13].atr$w_type = 0;     /* End of ATR list */
  150.     Atr[13].atr$w_size = 0;
  151.     Atr[13].atr$l_addr = (byte *)NULL;
  152.  
  153.     /* initialize RMS structures, we need a NAM to retrieve the FID */
  154.     Fab = cc$rms_fab;
  155.     Fab.fab$l_fna = file ; /* name of file */
  156.     Fab.fab$b_fns = strlen(file);
  157.     Fab.fab$l_nam = &Nam; /* FAB has an associated NAM */
  158.     Nam = cc$rms_nam;
  159.     Nam.nam$l_esa = EName; /* expanded filename */
  160.     Nam.nam$b_ess = sizeof(EName);
  161.     Nam.nam$l_rsa = RName; /* resultant filename */
  162.     Nam.nam$b_rss = sizeof(RName);
  163.  
  164.     /* do $PARSE and $SEARCH here */
  165.     status = sys$parse(&Fab);
  166.     if (!(status & 1)) return NULL;
  167.  
  168.     /* search for the first file.. If none signal error */
  169.     status = sys$search(&Fab);
  170.     if (!(status & 1)) return NULL;
  171.  
  172.     /* initialize Device name length, note that this points into the NAM
  173.          to get the device name filled in by the $PARSE, $SEARCH services */
  174.     DevDesc.dsc$w_length = Nam.nam$t_dvi[0];
  175.  
  176.     status = sys$assign(&DevDesc,&ctx->chan,0,0);
  177.     if (!(status & 1)) return NULL;
  178.  
  179.     FileName.dsc$a_pointer = Nam.nam$l_name;
  180.     FileName.dsc$w_length = Nam.nam$b_name+Nam.nam$b_type+Nam.nam$b_ver;
  181.  
  182.     /* Initialize the FIB */
  183.     Fib.FIB$L_ACCTL = FIB$M_NOWRITE;
  184.     for (i=0;i<3;i++)
  185.         Fib.FIB$W_FID[i]=Nam.nam$w_fid[i];
  186.     for (i=0;i<3;i++)
  187.         Fib.FIB$W_DID[i]=Nam.nam$w_did[i];
  188.  
  189.     /* Use the IO$_ACCESS function to return info about the file */
  190.     status = sys$qiow(0,ctx->chan,IO$_ACCESS|IO$M_ACCESS,&ctx->iosb,0,0,
  191.                     &FibDesc,&FileName,0,0,&Atr,0);
  192.  
  193.     if (ERR(status) || ERR(status = ctx->iosb.status))
  194.     {
  195.         vms_close(ctx);
  196.         return NULL;
  197.     }
  198.  
  199.     fat = (struct fatdef *)&(ctx -> PKi.ra);
  200.  
  201. #define SWAPW(x)        ( (((x)>>16)&0xFFFF) + ((x)<<16) )
  202.  
  203.     efblk = SWAPW(fat->fat$l_efblk);
  204.     hiblk = SWAPW(fat->fat$l_hiblk);
  205.  
  206.     if( efblk == 0 && fat -> fat$w_ffbyte == 0 )
  207.         ctx -> size =
  208.         ctx -> rest = hiblk * 512;
  209.     else
  210.         ctx -> size =
  211.         ctx -> rest = (efblk - 1) * 512 + fat -> fat$w_ffbyte;
  212.  
  213.     ctx -> status = SS$_NORMAL;
  214.     ctx -> vbn = 1;
  215.     return ctx;
  216. }
  217.  
  218. #define KByte 1024
  219.  
  220. /*----------------*
  221.  |   vms_read()   |
  222.  *----------------*
  223.  |   Reads file block by block into the buffer.
  224.  |   Stops on EOF, returns number of bytes actually read.
  225.  |   Note: size of the buffer must be greater than or equal to 512 !
  226.  */
  227.  
  228. int vms_read(ctx, buf, size)
  229. register struct ioctx *ctx;
  230. register char *buf;
  231. register int size;
  232. {
  233.     int status;
  234.     long nr=0;
  235.  
  236.     if (ctx -> rest <= 0 || ctx -> status == SS$_ENDOFFILE)
  237.         return 0;               /* Eof */
  238.  
  239.     if(size <= 0)
  240.         return 0;
  241.  
  242.     if(size > 16*KByte)
  243.         size = 16*KByte;
  244.     else if(size > 512)
  245.         size &= ~511L;          /* Round to integer number of blocks */
  246.  
  247.     do
  248.     {
  249.         status = sys$qiow(0, ctx->chan, IO$_READVBLK,
  250.             &ctx->iosb, 0, 0,
  251.             buf, size, ctx->vbn,0,0,0);
  252.  
  253.         ctx->vbn += size>>9;
  254.         if( size < 512 )
  255.                 ++ctx->vbn;
  256.  
  257.         if( !ERR(status) )
  258.                 status = ctx->iosb.status;
  259.  
  260.         if( !ERR(status) || status == SS$_ENDOFFILE )
  261.         {
  262.             register int count;
  263.  
  264.             if( status == SS$_ENDOFFILE )
  265.                 count = ctx->rest;
  266.             else
  267.                 count = ctx->iosb.count;
  268.  
  269.             size -= count;
  270.             buf  += count;
  271.             nr   += count;
  272.         }
  273.     } while( !ERR(status) && size > 0 );
  274.  
  275.     if (!ERR(status))
  276.     {
  277.         ctx -> status = SS$_NORMAL;
  278.         ctx -> rest -= nr;
  279.     }
  280.     else if(status == SS$_ENDOFFILE)
  281.     {
  282.         ctx -> status = SS$_ENDOFFILE;
  283.         ctx -> rest = 0;
  284.     }
  285.     else
  286.     {
  287.         ctx -> status = status;
  288.         ctx -> rest -= nr;
  289.     }
  290.     return nr;
  291. }
  292.  
  293. /*-----------------*
  294.  |   vms_error()   |
  295.  *-----------------*
  296.  |   Returns whether last operation on the file caused an error
  297.  */
  298.  
  299. int vms_error(ctx)
  300. struct ioctx *ctx;
  301. {   /* EOF is not actual error */
  302.     return ERR(ctx->status) && (ctx->status != SS$_ENDOFFILE);
  303. }
  304.  
  305. /*------------------*
  306.  |   vms_rewind()   |
  307.  *------------------*
  308.  |   Rewinds file to the beginning for the next vms_read().
  309.  */
  310.  
  311. int vms_rewind(ctx)
  312. struct ioctx *ctx;
  313. {
  314.     ctx -> vbn = 1;
  315.     ctx -> rest = ctx -> size;
  316.     return 0;
  317. }
  318.  
  319. /*--------------------------*
  320.  |   vms_get_attributes()   |
  321.  *--------------------------*
  322.  |   Returns pointer to malloc'ed PKWARE extra field with file attributes.
  323.  |   File must be open already by vms_open()
  324.  */
  325.  
  326. void vms_get_attributes(ctx, z, z_utim)
  327. struct ioctx *ctx;
  328. struct zlist far *z;    /* zip entry to compress */
  329. iztimes *z_utim;
  330. {
  331.     byte    *p, *b;
  332.     struct  PK_header    *h;
  333.     int     l;
  334.  
  335.     if( !vms_native )
  336.     {
  337. #ifdef USE_EF_UT_TIME
  338.         /*
  339.          *  A `portable' zipfile entry is created. Create an "UT" extra block
  340.          *  containing UNIX style modification time stamp in UTC, which helps
  341.          *  maintaining the `real' "last modified" time when the archive is
  342.          *  transfered across time zone boundaries.
  343.          */
  344.         if ((b = (uch *)malloc(EB_HEADSIZE+EB_UT_LEN(1))) == NULL)
  345.             return;
  346.  
  347.         b[0]  = 'U';
  348.         b[1]  = 'T';
  349.         b[2]  = EB_UT_LEN(1);          /* length of data part of e.f. */
  350.         b[3]  = 0;
  351.         b[4]  = EB_UT_FL_MTIME;
  352.         b[5]  = (byte)(z_utim->mtime);
  353.         b[6]  = (byte)(z_utim->mtime >> 8);
  354.         b[7]  = (byte)(z_utim->mtime >> 16);
  355.         b[8]  = (byte)(z_utim->mtime >> 24);
  356.  
  357.         z->cext = z->ext = (EB_HEADSIZE+EB_UT_LEN(1));
  358.         z->cextra = z->extra = (char*)b;
  359. #endif /* USE_EF_UT_TIME */
  360.  
  361.         return;
  362.     }
  363.  
  364.     l = PK_HEADER_SIZE+sizeof(ctx->PKi);
  365.     if(ctx->acllen > 0)
  366.         l += PK_FLDHDR_SIZE + ctx->acllen;
  367.  
  368.     b = (uch *)malloc(l);
  369.     if( b==NULL )
  370.         return;
  371.  
  372.     h = (struct PK_header *)b;
  373.     h->tag = PK_SIGNATURE;
  374.     h->size = l - EB_HEADSIZE;
  375.     p = (h->data);
  376.  
  377.     /* Copy default set of attributes */
  378.     memcpy(h->data,(uch*)&(ctx->PKi),sizeof(ctx->PKi));
  379.     p += sizeof(ctx->PKi);
  380.  
  381.     if( ctx->acllen > 0 )
  382.     {
  383.         struct PK_field *f;
  384.  
  385.         if(dosify)
  386.             zipwarn("file has ACL, may be incompatible with PKUNZIP","");
  387.  
  388.         f = (struct PK_field *)p;
  389.         f->tag = ATR$C_ADDACLENT;
  390.         f->size = ctx->acllen;
  391.         memcpy((char *)&(f->value[0]),ctx->aclbuf,ctx->acllen);
  392.         p += PK_FLDHDR_SIZE + ctx->acllen;
  393.     }
  394.  
  395.  
  396.     h->crc32 = crc32(0L, (uch *)NULL, 0);   /* Init CRC register */
  397.     h->crc32 = crc32(h->crc32, (uch *)(h->data), l - PK_HEADER_SIZE);
  398.  
  399.     z->ext = z->cext = l;
  400.     z->extra = z->cextra = (char *)b;
  401. }
  402.  
  403. int vms_close(ctx)
  404. struct ioctx *ctx;
  405. {
  406.         sys$dassgn(ctx->chan);
  407.         free(ctx);
  408.         return 0;
  409. }
  410.  
  411. #endif /* !_UTIL */
  412. #endif /* VMS */
  413.