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 + -
显示快捷键?