📄 fileio.c
字号:
if ((G.outfile = fopen(G.filename, FOPW)) == (FILE *)NULL) { Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile), FnFilter1(G.filename))); return 1; } Trace((stderr, "open_outfile: fopen(%s) for writing succeeded\n", FnFilter1(G.filename)));#endif /* !TANDEM */#endif /* !MTS */#endif /* !TOPS20 */#ifdef USE_FWRITE#ifdef DOS_OS2_W32 /* 16-bit MSC: buffer size must be strictly LESS than 32K (WSIZE): bogus */ setbuf(G.outfile, (char *)NULL); /* make output unbuffered */#else /* !DOS_OS2_W32 */#ifndef RISCOS#ifdef _IOFBF /* make output fully buffered (works just about like write()) */ setvbuf(G.outfile, (char *)slide, _IOFBF, WSIZE);#else setbuf(G.outfile, (char *)slide);#endif#endif /* !RISCOS */#endif /* ?DOS_OS2_W32 */#endif /* USE_FWRITE */ return 0;} /* end function open_outfile() */#endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS *//* * These functions allow NEXTBYTE to function without needing two bounds * checks. Call defer_leftover_input() if you ever have filled G.inbuf * by some means other than readbyte(), and you then want to start using * NEXTBYTE. When going back to processing bytes without NEXTBYTE, call * undefer_input(). For example, extract_or_test_member brackets its * central section that does the decompression with these two functions. * If you need to check the number of bytes remaining in the current * file while using NEXTBYTE, check (G.csize + G.incnt), not G.csize. *//****************************//* function undefer_input() *//****************************/void undefer_input(__G) __GDEF{ if (G.incnt > 0) G.csize += G.incnt; if (G.incnt_leftover > 0) { /* We know that "(G.csize < MAXINT)" so we can cast G.csize to int: * This condition was checked when G.incnt_leftover was set > 0 in * defer_leftover_input(), and it is NOT allowed to touch G.csize * before calling undefer_input() when (G.incnt_leftover > 0) * (single exception: see read_byte()'s "G.csize <= 0" handling) !! */ G.incnt = G.incnt_leftover + (int)G.csize; G.inptr = G.inptr_leftover - (int)G.csize; G.incnt_leftover = 0; } else if (G.incnt < 0) G.incnt = 0;} /* end function undefer_input() *//***********************************//* function defer_leftover_input() *//***********************************/void defer_leftover_input(__G) __GDEF{ if ((long)G.incnt > G.csize) { /* (G.csize < MAXINT), we can safely cast it to int !! */ if (G.csize < 0L) G.csize = 0L; G.inptr_leftover = G.inptr + (int)G.csize; G.incnt_leftover = G.incnt - (int)G.csize; G.incnt = (int)G.csize; } else G.incnt_leftover = 0; G.csize -= G.incnt;} /* end function defer_leftover_input() *//**********************//* Function readbuf() *//**********************/unsigned readbuf(__G__ buf, size) /* return number of bytes read into buf */ __GDEF char *buf; register unsigned size;{ register unsigned count; unsigned n; n = size; while (size) { if (G.incnt <= 0) { if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) return (n-size); else if (G.incnt < 0) { /* another hack, but no real harm copying same thing twice */ (*G.message)((zvoid *)&G, (uch *)LoadFarString(ReadError), /* CANNOT use slide */ (ulg)strlen(LoadFarString(ReadError)), 0x401); return 0; /* discarding some data; better than lock-up */ } /* buffer ALWAYS starts on a block boundary: */ G.cur_zipfile_bufstart += INBUFSIZ; G.inptr = G.inbuf; } count = MIN(size, (unsigned)G.incnt); memcpy(buf, G.inptr, count); buf += count; G.inptr += count; G.incnt -= count; size -= count; } return n;} /* end function readbuf() *//***********************//* Function readbyte() *//***********************/int readbyte(__G) /* refill inbuf and return a byte if available, else EOF */ __GDEF{ if (G.mem_mode) return EOF; if (G.csize <= 0) { G.csize--; /* for tests done after exploding */ G.incnt = 0; return EOF; } if (G.incnt <= 0) { if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) { G.incnt = 0; /* do not allow negative value to affect stuff */ return EOF; } else if (G.incnt < 0) { /* "fail" (abort, retry, ...) returns this */ /* another hack, but no real harm copying same thing twice */ (*G.message)((zvoid *)&G, (uch *)LoadFarString(ReadError), (ulg)strlen(LoadFarString(ReadError)), 0x401); echon();#ifdef WINDLL longjmp(dll_error_return, 1);#else DESTROYGLOBALS() EXIT(PK_BADERR); /* totally bailing; better than lock-up */#endif } G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on block bndry */ G.inptr = G.inbuf; defer_leftover_input(__G); /* decrements G.csize */ }#if CRYPT if (G.pInfo->encrypted) { uch *p; int n; /* This was previously set to decrypt one byte beyond G.csize, when * incnt reached that far. GRR said, "but it's required: why?" This * was a bug in fillinbuf() -- was it also a bug here? */ for (n = G.incnt, p = G.inptr; n--; p++) zdecode(*p); }#endif /* CRYPT */ --G.incnt; return *G.inptr++;} /* end function readbyte() */#ifdef USE_ZLIB/************************//* Function fillinbuf() *//************************/int fillinbuf(__G) /* like readbyte() except returns number of bytes in inbuf */ __GDEF{ if (G.mem_mode || (G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0) return 0; G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on a block boundary */ G.inptr = G.inbuf; defer_leftover_input(__G); /* decrements G.csize */#if CRYPT if (G.pInfo->encrypted) { uch *p; int n; for (n = G.incnt, p = G.inptr; n--; p++) zdecode(*p); }#endif /* CRYPT */ return G.incnt;} /* end function fillinbuf() */#endif /* USE_ZLIB */#ifndef VMS /* for VMS use code in vms.c *//********************//* Function flush() */ /* returns PK error codes: *//********************/ /* if cflag => always 0; PK_DISK if write error */int flush(__G__ rawbuf, size, unshrink) __GDEF uch *rawbuf; ulg size; int unshrink;{ register uch *p, *q; uch *transbuf;#if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV)) ulg transbufsiz;#endif /* static int didCRlast = FALSE; moved to globals.h *//*--------------------------------------------------------------------------- Compute the CRC first; if testing or if disk is full, that's it. ---------------------------------------------------------------------------*/ G.crc32val = crc32(G.crc32val, rawbuf, (extent)size);#ifdef DLL if ((G.statreportcb != NULL) && (*G.statreportcb)(__G__ UZ_ST_IN_PROGRESS, G.zipfn, G.filename, NULL)) return IZ_CTRLC; /* cancel operation by user request */#endif if (uO.tflag || size == 0L) /* testing or nothing to write: all done */ return PK_OK; if (G.disk_full) return PK_DISK; /* disk already full: ignore rest of file *//*--------------------------------------------------------------------------- Write the bytes rawbuf[0..size-1] to the output device, first converting end-of-lines and ASCII/EBCDIC as needed. If SMALL_MEM or MED_MEM are NOT defined, outbuf is assumed to be at least as large as rawbuf and is not necessarily checked for overflow. ---------------------------------------------------------------------------*/ if (!G.pInfo->textmode) { /* write raw binary data */ /* GRR: note that for standard MS-DOS compilers, size argument to * fwrite() can never be more than 65534, so WriteError macro will * have to be rewritten if size can ever be that large. For now, * never more than 32K. Also note that write() returns an int, which * doesn't necessarily limit size to 32767 bytes if write() is used * on 16-bit systems but does make it more of a pain; however, because * at least MSC 5.1 has a lousy implementation of fwrite() (as does * DEC Ultrix cc), write() is used anyway. */#ifdef DLL if (G.redirect_data) writeToMemory(__G__ rawbuf, size); else#endif if (!uO.cflag && WriteError(rawbuf, size, G.outfile)) return disk_error(__G); else if (uO.cflag && (*G.message)((zvoid *)&G, rawbuf, size, 0)) return 0; } else { /* textmode: aflag is true */ if (unshrink) { /* rawbuf = outbuf */ transbuf = G.outbuf2;#if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV)) transbufsiz = TRANSBUFSIZ;#endif } else { /* rawbuf = slide */ transbuf = G.outbuf;#if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV)) transbufsiz = OUTBUFSIZ; Trace((stderr, "\ntransbufsiz = OUTBUFSIZ = %u\n", OUTBUFSIZ));#endif } if (G.newfile) {#ifdef VMS_TEXT_CONV /* GRR: really want to check if -aa (or -aaa?) was given... */ if (rawbuf[1]) { /* first line is more than 255 chars long */ Trace((stderr, "\nfirst line of VMS `text' too long; switching to normal extraction\n")); G.VMS_line_state = -1; /* -1: don't treat as VMS text */ } else G.VMS_line_state = 0; /* 0: ready to read line length */#endif G.didCRlast = FALSE; /* no previous buffers written */ G.newfile = FALSE; }#ifdef VMS_TEXT_CONV if (G.pInfo->hostnum == VMS_ && G.extra_field && G.VMS_line_state >= 0) { /* GRR: really want to check for actual VMS extra field, and * ideally for variable-length record format *//* printf("\n>>>>>> GRR: file is VMS text and has an extra field\n"); */ p = rawbuf; q = transbuf; while(p < rawbuf+(unsigned)size) { switch (G.VMS_line_state) { /* 0: ready to read line length */ case 0: G.VMS_line_length = 0; G.VMS_line_pad = 0; if (p == rawbuf+(unsigned)size-1) { /* last char */ G.VMS_line_length = (int)((uch)(*p++)); G.VMS_line_state = 1; } else { G.VMS_line_length = makeword(p); p += 2; G.VMS_line_state = 2; } if (G.VMS_line_length & 1) /* odd */ G.VMS_line_pad = 1; break; /* 1: read one byte of length, need second */ case 1: G.VMS_line_length += ((int)((uch)(*p++)) << 8); G.VMS_line_state = 2; break; /* 2: ready to read VMS_line_length chars */ case 2: if (G.VMS_line_length < rawbuf+(unsigned)size-p) { if (G.VMS_line_length >= transbuf+(unsigned)transbufsiz-q) { int outroom = transbuf+(unsigned)transbufsiz-q;/* GRR: need to change this to *q++ = native(*p++); loop or something */ memcpy(q, p, outroom);#ifdef DLL if (G.redirect_data)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -