📄 vms.c
字号:
{ int status; if (pka_io_pending) { status = sys$synch(0, &pka_io_sb); if (!ERR(status)) status = pka_io_sb.status; if (ERR(status)) { vms_msg(__G__ "[ WriteQIO: sys$synch found I/O failure ]\n", status); return PK_DISK; } pka_io_pending = FALSE; } /* * Put content of buffer as a single VB */ status = sys$qio(0, pka_devchn, IO$_WRITEVBLK, &pka_io_sb, 0, 0, buf, len, pka_vbn, 0, 0, 0); if (ERR(status)) { vms_msg(__G__ "[ WriteQIO: sys$qio failed ]\n", status); return PK_DISK; } pka_io_pending = TRUE; pka_vbn += (len>>9); return PK_COOL;}/* 2004-10-01 SMS. Changed to clear the extra byte written out by qio() and sys$write() when an odd byte count is incremented to the next even value, either explicitly (qio), or implicitly (sys$write), on the theory that a reliable NUL beats left-over garbage. Alpha and VAX object files seem frequently to have even more than one byte of extra junk past EOF, so this may not help them.*/static int _flush_qio(__G__ rawbuf, size, final_flag) /* Asynchronous version */ __GDEF uch *rawbuf; unsigned size; int final_flag; /* 1 if this is the final flushout */{ int status; unsigned off = 0; while (size > 0) { if (curbuf->bufcnt < BUFS512) { unsigned ncpy; ncpy = size > (BUFS512 - curbuf->bufcnt) ? (BUFS512 - curbuf->bufcnt) : size; memcpy(curbuf->buf + curbuf->bufcnt, rawbuf + off, ncpy); size -= ncpy; curbuf->bufcnt += ncpy; off += ncpy; } if (curbuf->bufcnt == BUFS512) { status = WriteQIO(__G__ curbuf->buf, curbuf->bufcnt); if (status) return status; curbuf = curbuf->next; curbuf->bufcnt = 0; } } if (final_flag && (curbuf->bufcnt > 0)) { unsigned bufcnt_even; /* Round up to an even byte count. */ bufcnt_even = (curbuf->bufcnt+1) & (~1); /* If there is one, clear the extra byte. */ if (bufcnt_even > curbuf->bufcnt) curbuf->buf[curbuf->bufcnt] = '\0'; return WriteQIO(curbuf->buf, bufcnt_even); } else { return PK_COOL; }}#else /* !ASYNCH_QIO */static int _flush_qio(__G__ rawbuf, size, final_flag) __GDEF uch *rawbuf; unsigned size; int final_flag; /* 1 if this is the final flushout */{ int status; uch *out_ptr=rawbuf; if ( final_flag ) { if ( loccnt > 0 ) { unsigned loccnt_even; /* Round up to an even byte count. */ loccnt_even = (loccnt+1) & (~1); /* If there is one, clear the extra byte. */ if (loccnt_even > loccnt) locbuf[ loccnt] = '\0'; status = sys$qiow(0, pka_devchn, IO$_WRITEVBLK, &pka_io_sb, 0, 0, locbuf, loccnt_even, pka_vbn, 0, 0, 0); if (!ERR(status)) status = pka_io_sb.status; if (ERR(status)) { vms_msg(__G__ "[ Write QIO failed ]\n", status); return PK_DISK; } } return PK_COOL; } if ( loccnt > 0 ) { /* * Fill local buffer upto 512 bytes then put it out */ unsigned ncpy; ncpy = 512-loccnt; if ( ncpy > size ) ncpy = size; memcpy(locptr, out_ptr, ncpy); locptr += ncpy; loccnt += ncpy; size -= ncpy; out_ptr += ncpy; if ( loccnt == 512 ) { status = sys$qiow(0, pka_devchn, IO$_WRITEVBLK, &pka_io_sb, 0, 0, locbuf, loccnt, pka_vbn, 0, 0, 0); if (!ERR(status)) status = pka_io_sb.status; if (ERR(status)) { vms_msg(__G__ "[ Write QIO failed ]\n", status); return PK_DISK; } pka_vbn++; loccnt = 0; locptr = locbuf; } } if ( size >= 512 ) { unsigned nblk, put_cnt; /* * Put rest of buffer as a single VB */ put_cnt = (nblk = size>>9)<<9; status = sys$qiow(0, pka_devchn, IO$_WRITEVBLK, &pka_io_sb, 0, 0, out_ptr, put_cnt, pka_vbn, 0, 0, 0); if (!ERR(status)) status = pka_io_sb.status; if (ERR(status)) { vms_msg(__G__ "[ Write QIO failed ]\n", status); return PK_DISK; } pka_vbn += nblk; out_ptr += put_cnt; size -= put_cnt; } if ( size > 0 ) { memcpy(locptr, out_ptr, size); loccnt += size; locptr += size; } return PK_COOL;}#endif /* ?ASYNCH_QIO *//* * The routine _flush_varlen() requires: "(size & 1) == 0" * (The variable-length record algorithm assumes an even byte-count!) */static int _flush_varlen(__G__ rawbuf, size, final_flag) __GDEF uch *rawbuf; unsigned size; int final_flag;{ unsigned nneed; unsigned reclen; uch *inptr=rawbuf; /* * Flush local buffer */ if ( loccnt > 0 ) /* incomplete record left from previous call */ { reclen = *(ush*)locbuf; nneed = reclen + 2 - loccnt; if ( nneed > size ) { if ( size+loccnt > BUFSMAXREC ) { char buf[80]; Info(buf, 1, (buf, "[ Record too long (%u bytes) ]\n", reclen)); return PK_DISK; } memcpy(locbuf+loccnt, inptr, size); loccnt += size; size = 0; } else { memcpy(locbuf+loccnt, inptr, nneed); loccnt += nneed; size -= nneed; inptr += nneed; if ( reclen & 1 ) { size--; inptr++; } if ( WriteRecord(__G__ locbuf+2, reclen) ) return PK_DISK; loccnt = 0; } } /* * Flush incoming records */ while (size > 0) { reclen = *(ush*)inptr; if ( reclen+2 <= size ) { if (WriteRecord(__G__ inptr+2, reclen)) return PK_DISK; size -= 2+reclen; inptr += 2+reclen; if ( reclen & 1 ) { --size; ++inptr; } } else { memcpy(locbuf, inptr, size); loccnt = size; size = 0; } } /* * Final flush rest of local buffer */ if ( final_flag && loccnt > 0 ) { char buf[80]; Info(buf, 1, (buf, "[ Warning, incomplete record of length %u ]\n", (unsigned)*(ush*)locbuf)); if ( WriteRecord(__G__ locbuf+2, loccnt-2) ) return PK_DISK; } return PK_COOL;}/* * Routine _flush_stream breaks decompressed stream into records * depending on format of the stream (fab->rfm, G.pInfo->textmode, etc.) * and puts out these records. It also handles CR LF sequences. * Should be used when extracting *text* files. */#define VT 0x0B#define FF 0x0C/* The file is from MSDOS/OS2/NT -> handle CRLF as record end, throw out ^Z *//* GRR NOTES: cannot depend on hostnum! May have "flip'd" file or re-zipped * a Unix file, etc. */#ifdef USE_ORIG_DOS# define ORG_DOS \ (G.pInfo->hostnum==FS_FAT_ \ || G.pInfo->hostnum==FS_HPFS_ \ || G.pInfo->hostnum==FS_NTFS_)#else# define ORG_DOS 1#endif/* Record delimiters */#ifdef undef#define RECORD_END(c,f) \( ( ORG_DOS || G.pInfo->textmode ) && c==CTRLZ \ || ( f == FAB$C_STMLF && c==LF ) \ || ( f == FAB$C_STMCR || ORG_DOS || G.pInfo->textmode ) && c==CR \ || ( f == FAB$C_STM && (c==CR || c==LF || c==FF || c==VT) ) \)#else# define RECORD_END(c,f) ((c) == LF || (c) == (CR))#endifstatic unsigned find_eol(p,n,l)/* * Find first CR, LF, CR/LF or LF/CR in string 'p' of length 'n'. * Return offset of the sequence found or 'n' if not found. * If found, return in '*l' length of the sequence (1 or 2) or * zero if sequence end not seen, i.e. CR or LF is last char * in the buffer. */ uch *p; unsigned n; unsigned *l;{ unsigned off = n; uch *q; *l = 0; for (q=p ; n > 0 ; --n,++q) if ( RECORD_END(*q,rfm) ) { off = q-p; break; } if ( n > 1 ) { *l = 1; if ( ( q[0] == CR && q[1] == LF ) || ( q[0] == LF && q[1] == CR ) ) *l = 2; } return off;}/* Record delimiters that must be put out */#define PRINT_SPEC(c) ( (c)==FF || (c)==VT )static int _flush_stream(__G__ rawbuf, size, final_flag) __GDEF uch *rawbuf; unsigned size; int final_flag; /* 1 if this is the final flushout */{ int rest; unsigned end = 0, start = 0; if (size == 0 && loccnt == 0) return PK_COOL; /* Nothing to do ... */ if ( final_flag ) { unsigned recsize; /* * This is flush only call. size must be zero now. * Just eject everything we have in locbuf. */ recsize = loccnt - (got_eol ? 1 : 0); /* * If the last char of file was ^Z ( end-of-file in MSDOS ), * we will see it now. */ if ( recsize==1 && locbuf[0] == CTRLZ ) return PK_COOL; return WriteRecord(__G__ locbuf, recsize); } if ( loccnt > 0 ) { /* Find end of record partially saved in locbuf */ unsigned recsize; int complete=0; if ( got_eol ) { recsize = loccnt - 1; complete = 1; if ( (got_eol == CR && rawbuf[0] == LF) || (got_eol == LF && rawbuf[0] == CR) ) end = 1; got_eol = 0; } else { unsigned eol_len; unsigned eol_off; eol_off = find_eol(rawbuf, size, &eol_len); if ( loccnt+eol_off > BUFSMAXREC ) { /* * No room in locbuf. Dump it and clear */ char buf[80]; /* CANNOT use slide for Info() */ recsize = loccnt; start = 0; Info(buf, 1, (buf, "[ Warning: Record too long (%u) ]\n", loccnt+eol_off)); complete = 1; end = 0; } else { if ( eol_off >= size ) { end = size; complete = 0; } else if ( eol_len == 0 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -