📄 file_io.c
字号:
/*--------------------------------------------------------------------------- file_io.c This file contains routines for doing direct input/output, file-related sorts of things. Most of the system-specific code for unzip is contained here, including the non-echoing password code for decryption (bottom). ---------------------------------------------------------------------------*/#define const#include "unzip.h"/************************************//* File_IO Local Prototypes, etc. *//************************************/#ifndef DOS_OS2 static int dos2unix __((unsigned char *buf, int len)); int CR_flag = 0; /* when last char of buffer == CR (for dos2unix()) */#endif#ifdef OS2 extern int longname; /* set in mapname.c */ extern char longfilename[];#endif#ifdef CRYPT typedef char voidp;# if defined(DOS_OS2) || defined(VMS)# define MSVMS# ifdef DOS_OS2# include <conio.h># else /* !DOS_OS2 */# define getch() getc(stderr)# define OFF 0 /* for echo control */# define ON 1# include <descrip.h># include <iodef.h># include <ttdef.h># ifndef SS$_NORMAL# define SS$_NORMAL 1 /* only thing we need from <ssdef.h> */# endif# endif /* ?DOS_OS2 */# else /* !(DOS_OS2 || VMS) */# ifdef TERMIO /* Amdahl, Cray, all SysV? */# ifdef CONVEX# include <sys/termios.h># include <sgtty.h># else /* !CONVEX */# include <sys/termio.h># define sgttyb termio# define sg_flags c_lflag# endif /* ?CONVEX */ int ioctl OF((int, int, voidp *));# define GTTY(f,s) ioctl(f,TCGETA,(voidp *)s)# define STTY(f,s) ioctl(f,TCSETAW,(voidp *)s)# else /* !TERMIO */# ifndef MINIX# include <sys/ioctl.h># endif /* !MINIX */# include <sgtty.h> int gtty OF((int, struct sgttyb *)); int stty OF((int, struct sgttyb *));# define GTTY gtty# define STTY stty# endif /* ?TERMIO */ int isatty OF((int)); char *ttyname OF((int)); int open OF((char *, int, ...)); int close OF((int)); int read OF((int, voidp *, int));# endif /* ?(DOS_OS2 || VMS) */#endif /* CRYPT *//******************************//* Function open_input_file() *//******************************/int open_input_file(){ /* return non-0 if open failed */ /* * open the zipfile for reading and in BINARY mode to prevent cr/lf * translation, which would corrupt the bitstreams */#ifdef UNIX zipfd = open(zipfn, O_RDONLY);#else zipfd = open(zipfn, O_RDONLY | O_BINARY);#endif if (zipfd < 1) { fprintf(stderr, "error: can't open zipfile [ %s ]\n", zipfn); return (1); } return 0;}/**********************//* Function readbuf() *//**********************/int readbuf(buf, size)char *buf;register unsigned size;{ /* return number of bytes read into buf */ register int count; int n; n = size; while (size) { if (incnt == 0) { if ((incnt = read(zipfd, (char *)inbuf, INBUFSIZ)) <= 0) return (n-size); /* buffer ALWAYS starts on a block boundary: */ cur_zipfile_bufstart += INBUFSIZ; inptr = inbuf; } count = min(size, incnt); memcpy(buf, inptr, count); buf += count; inptr += count; incnt -= count; size -= count; } return (n);}#ifndef VMS /* for VMS use code in vms.c (old VMS code below is retained * in case of problems...will be removed in a later release) *//*********************************//* Function create_output_file() *//*********************************/int create_output_file(){ /* return non-0 if creat failed *//*--------------------------------------------------------------------------- Create the output file with appropriate permissions. If we've gotten to this point and the file still exists, we have permission to blow it away. ---------------------------------------------------------------------------*/#ifndef DOS_OS2 CR_flag = 0; /* hack to get CR at end of buffer working */#endif#if defined(UNIX) && !defined(AMIGA) { int mask;#ifndef VMS if (!stat(filename, &statbuf) && (unlink(filename) < 0)) { fprintf(stderr, "\n%s: cannot delete old copy\n", filename); return 1; }# define EXTRA_ARGS#else /* VMS */# define EXTRA_ARGS ,"rfm=stmlf","rat=cr"#endif /* ?VMS */ mask = umask(0); /* now know we own it */ outfd = creat(filename, 0777 & pInfo->unix_attr EXTRA_ARGS); umask(mask); /* VMS, Unix */ }#else /* !UNIX || AMIGA */ /* file permissions set after file closed */#if defined(MACOS) && defined(MPW) && !defined(MCH_MACINTOSH) outfd = creat(filename); /* Mac MPW C compiler */#else /* !(Macintosh MPW 3.2 C) */ outfd = creat(filename, S_IWRITE | S_IREAD); /* DOS, OS2, Mac, Amiga */#endif /* ?(Macintosh MPW 3.2 C) */#endif /* ?(UNIX && !AMIGA) */ if (outfd < 1) { fprintf(stderr, "\n%s: cannot create\n", filename); return 1; }/*--------------------------------------------------------------------------- If newly created file is in text mode and should be binary (to disable automatic CR/LF translations), either close it and reopen as binary or else change the mode to binary (DOS, OS/2). If it is already binary and should be text, change the mode to text (Mac). ---------------------------------------------------------------------------*/#ifndef UNIX#ifdef THINK_C /* * THINKC's stdio routines have the horrible habit of * making any file you open look like generic files. * This code tells the OS that it's a text file. */ if (aflag) { fileParam pb; OSErr err; CtoPstr(filename); pb.ioNamePtr = (StringPtr)filename; pb.ioVRefNum = 0; pb.ioFVersNum = 0; pb.ioFDirIndex = 0; err = PBGetFInfo(&pb,0); if (err == noErr) { pb.ioFlFndrInfo.fdCreator = '\?\?\?\?'; pb.ioFlFndrInfo.fdType = 'TEXT'; err = PBSetFInfo(&pb, 0); } PtoCstr(filename); }#endif /* THINK_C */ if (!aflag) {#ifdef DOS_OS2 if (setmode(outfd, O_BINARY) == -1) {#else /* !DOS_OS2 */ close(outfd); if ((outfd = open(filename, O_RDWR | O_BINARY)) < 1) {#endif /* ?DOS_OS2 */ fprintf(stderr, "Can't make output file binary: %s\n", filename); return 1; } }#endif /* !UNIX */ return 0;}#endif /* !VMS *//****************************//* Function FillBitBuffer() *//****************************/int FillBitBuffer(){ /* * Fill bitbuf, which is 32 bits. This function is only used by the * READBIT and PEEKBIT macros (which are used by all of the uncompression * routines). */ UWORD temp; zipeof = 1; while (bits_left < 25 && ReadByte(&temp) == 8) { bitbuf |= (ULONG)temp << bits_left; bits_left += 8; zipeof = 0; } return 0;}/***********************//* Function ReadByte() *//***********************/int ReadByte(x)UWORD *x;{ /* * read a byte; return 8 if byte available, 0 if not */ if (csize-- <= 0) return 0; if (incnt == 0) { if ((incnt = read(zipfd, (char *)inbuf, INBUFSIZ)) <= 0) return 0; /* buffer ALWAYS starts on a block boundary: */ cur_zipfile_bufstart += INBUFSIZ; inptr = inbuf;#ifdef CRYPT if (pInfo->encrypted) { byte *p; int n, t; for (n = incnt > csize + 1 ? (int)csize + 1 : incnt, p = inptr; n--; p++) *p = DECRYPT(*p); }#endif /* CRYPT */ } *x = *inptr++; --incnt; return 8;}#ifndef VMS /* for VMS use code in vms.c *//**************************//* Function FlushOutput() *//**************************/int FlushOutput(){ /* * flush contents of output buffer; return PK-type error code */#ifndef DOS_OS2# define CTRLZ 26 int saved_ctrlZ = FALSE;#endif /* !DOS_OS2 */ int len; if (disk_full) { outpos += outcnt; /* fake emptied buffer */ outcnt = 0; outptr = outbuf; return 50; /* ignore rest of this file */ } if (outcnt) { UpdateCRC(outbuf, outcnt); if (!tflag) {#ifndef DOS_OS2 if (aflag) { if (outbuf[outcnt-1] == CTRLZ) { --outcnt; saved_ctrlZ = TRUE; } len = dos2unix(outbuf, outcnt); } else#endif /* !DOS_OS2 */ len = outcnt; if (write(outfd, (char *)outout, len) != len)#ifdef DOS_OS2 if (!cflag) /* ^Z treated as EOF, removed with -c */#else /* !DOS_OS2 */#ifdef MINIX if (errno == EFBIG) if (write(fd, outout, len/2) != len/2 || write(fd, outout+len/2, len/2) != len/2)#endif /* MINIX */#endif /* ?DOS_OS2 */ { /* GRR: add test for force_flag when has its own switch */ fprintf(stderr, "\n%s: write error (disk full?). Continue? (y/n/^C) ", filename); FFLUSH /* for Amiga and Mac MPW */ fgets(answerbuf, 9, stdin); if (*answerbuf == 'y') /* stop writing to this file */ disk_full = 1; /* (outfd bad?), but new OK */ else disk_full = 2; /* no: exit program */ return 50; /* 50: disk full */ } } outpos += outcnt; outcnt = 0; outptr = outbuf;#ifndef DOS_OS2 if (saved_ctrlZ) { *outptr++ = CTRLZ; ++outcnt; }#endif /* !DOS_OS2 */ } return (0); /* 0: no error */}#endif /* !VMS */#ifndef DOS_OS2 /* GRR: rewrite this for generic text conversions *//***********************//* Function dos2unix() *//***********************/static int dos2unix(buf, len)unsigned char *buf;int len;{ int new_len; int i; unsigned char *walker; new_len = len; walker = outout;#ifdef MACOS /* * Mac wants to strip LFs instead CRs from CRLF pairs */ if (CR_flag && *buf == LF) { buf++; new_len--; len--; CR_flag = buf[len] == CR; } else CR_flag = buf[len - 1] == CR; for (i = 0; i < len; i += 1) { *walker++ = ascii_to_native(*buf); if (*buf == LF) walker[-1] = CR; if (*buf++ == CR && *buf == LF) { new_len--; buf++; i++; } }#else if (CR_flag && *buf != LF) *walker++ = ascii_to_native(CR); CR_flag = buf[len - 1] == CR; for (i = 0; i < len; i += 1) { *walker++ = ascii_to_native(*buf); if (*buf++ == CR && *buf == LF) { new_len--; walker[-1] = ascii_to_native(*buf++); i++; } } /* * If the last character is a CR, then "ignore it" for now... */ if (walker[-1] == ascii_to_native(CR)) new_len--;#endif return new_len;}#endif /* !DOS_OS2 */#ifdef DOS_OS2/**************************************//* Function set_file_time_and_close() *//**************************************/void set_file_time_and_close() /* * MS-DOS AND OS/2 VERSION (Mac, Unix/VMS versions are below) * * Set the output file date/time stamp according to information from the * zipfile directory record for this member, then close the file and set * its permissions (archive, hidden, read-only, system). Aside from closing * the file, this routine is optional (but most compilers support it). */{/*--------------------------------------------------------------------------- Allocate local variables needed by OS/2 and Turbo C. ---------------------------------------------------------------------------*/#ifdef OS2 /* (assuming only MSC or MSC-compatible compilers * for this part) */ union { FDATE fd; /* system file date record */ UWORD zdate; /* date word */ } ud; union { FTIME ft; /* system file time record */ UWORD ztime; /* time word */ } ut; FILESTATUS fs;#else /* !OS2 */#ifdef __TURBOC__ union { struct ftime ft; /* system file time record */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -