vms_pk.c

来自「给出了 zip 压缩算法的完整实现过程。」· C语言 代码 · 共 551 行 · 第 1/2 页

C
551
字号
 |   vms_read()   | *----------------* |   Reads file in (multi-)block-sized chunks into the buffer. |   Stops on EOF. Returns number of bytes actually read. |   Note: This function makes no sense (and will error) if the buffer |   size ("size") is not a multiple of the disk block size (512). */size_t vms_read( ctx, buf, size)ioctx_t *ctx;char *buf;size_t size;{    int act_cnt;    int rest_rndup;    int status;    unsigned int bytes_read = 0;    /* If previous read hit EOF, fail early. */    if (ctx -> status == SS$_ENDOFFILE)        return 0;               /* EOF. */    /* If no more expected to be read, fail early. */    if (ctx -> rest == 0)        return 0;               /* Effective EOF. */    /* If request is smaller than a whole block, fail.       This really should never happen.  (assert()?)    */    if (size < BLOCK_BYTES)        return 0;    /* Note that on old VMS VAX versions (like V5.5-2), QIO[W] may fail       with status %x0000034c (= %SYSTEM-F-IVBUFLEN, invalid buffer       length) when size is not a multiple of 512.  Thus the requested       size is boosted as needed, but the IOSB byte count returned is       reduced when it exceeds the actual bytes remaining (->rest).    */    /* Adjust request size as appropriate. */    if (size > MAX_READ_BYTES)    {        /* Restrict request to MAX_READ_BYTES. */        size = MAX_READ_BYTES;    }    else    {        /* Round odd-ball request up to the next whole block.           This really should never happen.  (assert()?)        */        size = (size+ BLOCK_BYTES- 1)& ~(BLOCK_BYTES- 1);    }    rest_rndup = (ctx -> rest+ BLOCK_BYTES- 1)& ~(BLOCK_BYTES- 1);    /* Read (QIOW) until error or "size" bytes have been read. */    do    {        /* Reduce "size" when next (last) read would overrun the EOF,           but never below one block (so we'll always get a nice EOF).        */        if (size > rest_rndup)            size = rest_rndup;        status = sys$qiow( 0, ctx->chan, IO$_READVBLK,            &ctx->iosb, 0, 0,            buf, size, ctx->vbn, 0, 0, 0);        /* If initial status was good, use final status. */        if ( !ERR(status) )                status = ctx->iosb.status;        if ( !ERR(status) || status == SS$_ENDOFFILE )        {            act_cnt = ctx->iosb.count;            /* Ignore whole-block boost when remainder is smaller. */            if (act_cnt > ctx->rest)            {                act_cnt = ctx->rest;                status = SS$_ENDOFFILE;            }            /* Adjust counters/pointers according to delivered bytes. */            size -= act_cnt;            buf += act_cnt;            bytes_read += act_cnt;            ctx->vbn += ctx->iosb.count/ BLOCK_BYTES;        }    } while ( !ERR(status) && (size > 0) );    if (!ERR(status))    {        /* Record any successful status as SS$_NORMAL. */        ctx -> status = SS$_NORMAL;    }    else if (status == SS$_ENDOFFILE)    {        /* Record EOF as SS$_ENDOFFILE.  (Ignore error status codes?) */        ctx -> status = SS$_ENDOFFILE;    }    /* Decrement bytes-to-read.  Return the total bytes read. */    ctx -> rest -= bytes_read;    return bytes_read;}/*-----------------* |   vms_error()   | *-----------------* |   Returns whether last operation on the file caused an error */int vms_error(ctx)ioctx_t *ctx;{   /* EOF is not actual error */    return ERR(ctx->status) && (ctx->status != SS$_ENDOFFILE);}/*------------------* |   vms_rewind()   | *------------------* |   Rewinds file to the beginning for the next vms_read(). */int vms_rewind(ctx)ioctx_t *ctx;{    ctx -> vbn = 1;    ctx -> rest = ctx -> size;    return 0;}/*--------------------------* |   vms_get_attributes()   | *--------------------------* |   Malloc a PKWARE extra field and fill with file attributes. Returns |   error number of the ZE_??? class. |   If the passed ioctx record "FILE *" pointer is NULL, vms_open() is |   called to fetch the file attributes. |   When `vms_native' is not set, a generic "UT" type timestamp extra |   field is generated instead. | |   2004-11-11 SMS. |   Changed to use separate storage for ->extra and ->cextra.  Zip64 |   processing may move (reallocate) one and not the other. */int vms_get_attributes(ctx, z, z_utim)ioctx_t *ctx;           /* Internal file control structure. */struct zlist far *z;    /* Zip entry to compress. */iztimes *z_utim;{    byte    *p;    byte    *xtra;    byte    *cxtra;    struct  PK_header    *h;    extent  l;    int     notopened;    if ( !vms_native )    {#ifdef USE_EF_UT_TIME        /*         *  A `portable' zipfile entry is created. Create an "UT" extra block         *  containing UNIX style modification time stamp in UTC, which helps         *  maintaining the `real' "last modified" time when the archive is         *  transfered across time zone boundaries.         */#  ifdef IZ_CHECK_TZ        if (!zp_tz_is_valid)            return ZE_OK;       /* skip silently if no valid TZ info */#  endif        if ((xtra = (uch *) malloc( EB_HEADSIZE + EB_UT_LEN( 1))) == NULL)            return ZE_MEM;        if ((cxtra = (uch *) malloc( EB_HEADSIZE + EB_UT_LEN( 1))) == NULL)            return ZE_MEM;        /* Fill xtra[] with data. */        xtra[ 0] = 'U';        xtra[ 1] = 'T';        xtra[ 2] = EB_UT_LEN(1);        /* length of data part of e.f. */        xtra[ 3] = 0;        xtra[ 4] = EB_UT_FL_MTIME;        xtra[ 5] = (byte) (z_utim->mtime);        xtra[ 6] = (byte) (z_utim->mtime >> 8);        xtra[ 7] = (byte) (z_utim->mtime >> 16);        xtra[ 8] = (byte) (z_utim->mtime >> 24);        /* Copy xtra[] data into cxtra[]. */        memcpy( cxtra, xtra, (EB_HEADSIZE + EB_UT_LEN( 1)));        /* Set sizes and pointers. */        z->cext = z->ext = (EB_HEADSIZE + EB_UT_LEN( 1));        z->extra = (char*) xtra;        z->cextra = (char*) cxtra;#endif /* USE_EF_UT_TIME */        return ZE_OK;    }    notopened = (ctx == NULL);    if ( notopened && ((ctx = vms_open(z->name)) == NULL) )        return ZE_OPEN;    l = PK_HEADER_SIZE + sizeof(ctx->PKi);    if (ctx->acllen > 0)        l += PK_FLDHDR_SIZE + ctx->acllen;    if ((xtra = (uch *) malloc(l)) == NULL)        return ZE_MEM;    if ((cxtra = (uch *) malloc(l)) == NULL)        return ZE_MEM;    /* Fill xtra[] with data. */    h = (struct PK_header *) xtra;    h->tag = PK_SIGNATURE;    h->size = l - EB_HEADSIZE;    p = (h->data);    /* Copy default set of attributes */    memcpy(h->data, (char*)&(ctx->PKi), sizeof(ctx->PKi));    p += sizeof(ctx->PKi);    if ( ctx->acllen > 0 )    {        struct PK_field *f;        if (dosify)            zipwarn("file has ACL, may be incompatible with PKUNZIP","");        f = (struct PK_field *)p;        f->tag = ATR$C_ADDACLENT;        f->size = ctx->acllen;        memcpy((char *)&(f->value[0]), ctx->aclbuf, ctx->acllen);        p += PK_FLDHDR_SIZE + ctx->acllen;    }    h->crc32 = CRCVAL_INITIAL;                  /* Init CRC register */    h->crc32 = crc32(h->crc32, (uch *)(h->data), l - PK_HEADER_SIZE);    /* Copy xtra[] data into cxtra[]. */    memcpy( cxtra, xtra, l);    /* Set sizes and pointers. */    z->ext = z->cext = l;    z->extra = (char *) xtra;    z->cextra = (char *) cxtra;    if (notopened)              /* close "ctx", if we have opened it here */        vms_close(ctx);    return ZE_OK;}int vms_close(ctx)ioctx_t *ctx;{        sys$dassgn(ctx->chan);        free(ctx);        return 0;}#endif /* !_UTIL */#endif /* def VMS_PK_EXTRA */#endif /* VMS */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?