📄 fileio.c
字号:
#endif /* !BSD4_4 */#ifdef WIN32 }#endif#endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */#endif /* ?TOPS20 */#endif /* ?HAVE_MKTIME */ if ( (dosdatetime >= DOSTIME_2038_01_18) && (m_time < (time_t)0x70000000L) ) m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */ if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */ m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */ return m_time;} /* end function dos_to_unix_time() */#endif /* !OS2 || TIMESTAMP */#endif /* !VMS && !CMS_MVS */#if (!defined(VMS) && !defined(OS2) && !defined(CMS_MVS))/******************************//* Function check_for_newer() */ /* used for overwriting/freshening/updating *//******************************/int check_for_newer(__G__ filename) /* return 1 if existing file is newer */ __GDEF /* or equal; 0 if older; -1 if doesn't */ char *filename; /* exist yet */{ time_t existing, archive;#ifdef USE_EF_UT_TIME iztimes z_utime;#endif#ifdef AOS_VS long dyy, dmm, ddd, dhh, dmin, dss; dyy = (lrec.last_mod_dos_datetime >> 25) + 1980; dmm = (lrec.last_mod_dos_datetime >> 21) & 0x0f; ddd = (lrec.last_mod_dos_datetime >> 16) & 0x1f; dhh = (lrec.last_mod_dos_datetime >> 11) & 0x1f; dmin = (lrec.last_mod_dos_datetime >> 5) & 0x3f; dss = (lrec.last_mod_dos_datetime & 0x1f) * 2; /* under AOS/VS, file times can only be set at creation time, * with the info in a special DG format. Make sure we can create * it here - we delete it later & re-create it, whether or not * it exists now. */ if (!zvs_create(filename, (((ulg)dgdate(dmm, ddd, dyy)) << 16) | (dhh*1800L + dmin*30L + dss/2L), -1L, -1L, (char *) -1, -1, -1, -1)) return DOES_NOT_EXIST;#endif /* AOS_VS */ Trace((stderr, "check_for_newer: doing stat(%s)\n", FnFilter1(filename))); if (SSTAT(filename, &G.statbuf)) { Trace((stderr, "check_for_newer: stat(%s) returns %d: file does not exist\n", FnFilter1(filename), SSTAT(filename, &G.statbuf)));#ifdef SYMLINKS Trace((stderr, "check_for_newer: doing lstat(%s)\n", FnFilter1(filename))); /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */ if (lstat(filename, &G.statbuf) == 0) { Trace((stderr, "check_for_newer: lstat(%s) returns 0: symlink does exist\n", FnFilter1(filename))); if (QCOND2 && !uO.overwrite_all) Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink), FnFilter1(filename), " with no real file")); return EXISTS_AND_OLDER; /* symlink dates are meaningless */ }#endif /* SYMLINKS */ return DOES_NOT_EXIST; } Trace((stderr, "check_for_newer: stat(%s) returns 0: file exists\n", FnFilter1(filename)));#ifdef SYMLINKS /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */ if (lstat(filename, &G.statbuf) == 0 && S_ISLNK(G.statbuf.st_mode)) { Trace((stderr, "check_for_newer: %s is a symbolic link\n", FnFilter1(filename))); if (QCOND2 && !uO.overwrite_all) Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink), FnFilter1(filename), "")); return EXISTS_AND_OLDER; /* symlink dates are meaningless */ }#endif /* SYMLINKS */ NATIVE_TO_TIMET(G.statbuf.st_mtime) /* NOP unless MSC 7.0 or Macintosh */#ifdef USE_EF_UT_TIME /* The `Unix extra field mtime' should be used for comparison with the * time stamp of the existing file >>>ONLY<<< when the EF info is also * used to set the modification time of the extracted file. */ if (G.extra_field &&#ifdef IZ_CHECK_TZ G.tz_is_valid &&#endif (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime, &z_utime, NULL) & EB_UT_FL_MTIME)) { TTrace((stderr, "check_for_newer: using Unix extra field mtime\n")); existing = G.statbuf.st_mtime; archive = z_utime.mtime; } else { /* round up existing filetime to nearest 2 seconds for comparison, * but saturate in case of arithmetic overflow */ existing = ((G.statbuf.st_mtime & 1) && (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ? G.statbuf.st_mtime + 1 : G.statbuf.st_mtime; archive = dos_to_unix_time(G.lrec.last_mod_dos_datetime); }#else /* !USE_EF_UT_TIME */ /* round up existing filetime to nearest 2 seconds for comparison, * but saturate in case of arithmetic overflow */ existing = ((G.statbuf.st_mtime & 1) && (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ? G.statbuf.st_mtime + 1 : G.statbuf.st_mtime; archive = dos_to_unix_time(G.lrec.last_mod_dos_datetime);#endif /* ?USE_EF_UT_TIME */ TTrace((stderr, "check_for_newer: existing %lu, archive %lu, e-a %ld\n", (ulg)existing, (ulg)archive, (long)(existing-archive))); return (existing >= archive);} /* end function check_for_newer() */#endif /* !VMS && !OS2 && !CMS_MVS *//************************//* Function do_string() *//************************/int do_string(__G__ len, option) /* return PK-type error code */ __GDEF unsigned int len; /* without prototype, ush converted to this */ int option;{ long comment_bytes_left, block_length; int error=PK_OK; ush extra_len;#ifdef AMIGA char tmp_fnote[2 * AMIGA_FILENOTELEN]; /* extra room for squozen chars */#endif/*--------------------------------------------------------------------------- This function processes arbitrary-length (well, usually) strings. Four options are allowed: SKIP, wherein the string is skipped (pretty logical, eh?); DISPLAY, wherein the string is printed to standard output after un- dergoing any necessary or unnecessary character conversions; DS_FN, wherein the string is put into the filename[] array after undergoing ap- propriate conversions (including case-conversion, if that is indicated: see the global variable pInfo->lcflag); and EXTRA_FIELD, wherein the `string' is assumed to be an extra field and is copied to the (freshly malloced) buffer G.extra_field. The third option should be OK since filename is dimensioned at 1025, but we check anyway. The string, by the way, is assumed to start at the current file-pointer position; its length is given by len. So start off by checking length of string: if zero, we're already done. ---------------------------------------------------------------------------*/ if (!len) return PK_COOL; switch (option) { /* * First case: print string on standard output. First set loop vari- * ables, then loop through the comment in chunks of OUTBUFSIZ bytes, * converting formats and printing as we go. The second half of the * loop conditional was added because the file might be truncated, in * which case comment_bytes_left will remain at some non-zero value for * all time. outbuf and slide are used as scratch buffers because they * are available (we should be either before or in between any file pro- * cessing). */ case DISPLAY: case DISPL_8: comment_bytes_left = len; block_length = OUTBUFSIZ; /* for the while statement, first time */ while (comment_bytes_left > 0 && block_length > 0) { register uch *p = G.outbuf; register uch *q = G.outbuf; if ((block_length = readbuf(__G__ (char *)G.outbuf, (unsigned) MIN((long)OUTBUFSIZ, comment_bytes_left))) == 0) return PK_EOF; comment_bytes_left -= block_length; /* this is why we allocated an extra byte for outbuf: terminate * with zero (ASCIIZ) */ G.outbuf[(unsigned)block_length] = '\0'; /* remove all ASCII carriage returns from comment before printing * (since used before A_TO_N(), check for CR instead of '\r') */ while (*p) { while (*p == CR) ++p; *q++ = *p++; } /* could check whether (p - outbuf) == block_length here */ *q = '\0'; if (option == DISPL_8) { /* translate the text coded in the entry's host-dependent "extended ASCII" charset into the compiler's (system's) internal text code page */ Ext_ASCII_TO_Native((char *)G.outbuf, G.pInfo->hostnum, G.crec.version_made_by[0]);#ifdef WINDLL /* translate to ANSI (RTL internal codepage may be OEM) */ INTERN_TO_ISO((char *)G.outbuf, (char *)G.outbuf);#else /* !WINDLL */#ifdef WIN32 /* Win9x console always uses OEM character coding, and WinNT console is set to OEM charset by default, too */ INTERN_TO_OEM((char *)G.outbuf, (char *)G.outbuf);#endif /* WIN32 */#endif /* ?WINDLL */ } else { A_TO_N(G.outbuf); /* translate string to native */ }#ifdef WINDLL /* ran out of local mem -- had to cheat */ win_fprintf((zvoid *)&G, stdout, len, (char *)G.outbuf); win_fprintf((zvoid *)&G, stdout, 2, (char *)"\n\n");#else /* !WINDLL */#ifdef NOANSIFILT /* GRR: can ANSI be used with EBCDIC? */ (*G.message)((zvoid *)&G, G.outbuf, (ulg)(q-G.outbuf), 0);#else /* ASCII, filter out ANSI escape sequences and handle ^S (pause) */ p = G.outbuf - 1; q = slide; while (*++p) { int pause = FALSE; if (*p == 0x1B) { /* ASCII escape char */ *q++ = '^'; *q++ = '['; } else if (*p == 0x13) { /* ASCII ^S (pause) */ pause = TRUE; if (p[1] == LF) /* ASCII LF */ *q++ = *++p; else if (p[1] == CR && p[2] == LF) { /* ASCII CR LF */ *q++ = *++p; *q++ = *++p; } } else *q++ = *p; if ((unsigned)(q-slide) > WSIZE-3 || pause) { /* flush */ (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0); q = slide; if (pause && G.extract_flag) /* don't pause for list/test */ (*G.mpause)((zvoid *)&G, LoadFarString(QuitPrompt), 0); } } (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0);#endif /* ?NOANSIFILT */#endif /* ?WINDLL */ } /* add '\n' if not at start of line */ (*G.message)((zvoid *)&G, slide, 0L, 0x40); break; /* * Second case: read string into filename[] array. The filename should * never ever be longer than FILNAMSIZ-1 (1024), but for now we'll check, * just to be sure. */ case DS_FN: extra_len = 0; if (len >= FILNAMSIZ) { Info(slide, 0x401, ((char *)slide, LoadFarString(FilenameTooLongTrunc))); error = PK_WARN; extra_len = (ush)(len - FILNAMSIZ + 1); len = FILNAMSIZ - 1; } if (readbuf(__G__ G.filename, len) == 0) return PK_EOF; G.filename[len] = '\0'; /* terminate w/zero: ASCIIZ */ /* translate the Zip entry filename coded in host-dependent "extended ASCII" into the compiler's (system's) internal text code page */ Ext_ASCII_TO_Native(G.filename, G.pInfo->hostnum, G.crec.version_made_by[0]); if (G.pInfo->lcflag) /* replace with lowercase filename */ TOLOWER(G.filename, G.filename); if (G.pInfo->vollabel && len > 8 && G.filename[8] == '.') { char *p = G.filename+8; while (*p++) p[-1] = *p; /* disk label, and 8th char is dot: remove dot */ } if (!extra_len) /* we're done here */ break; /* * We truncated the filename, so print what's left and then fall * through to the SKIP routine. */ Info(slide, 0x401, ((char *)slide, "[ %s ]\n", FnFilter1(G.filename))); len = extra_len; /* FALL THROUGH... */ /* * Third case: skip string, adjusting readbuf's internal variables * as necessary (and possibly skipping to and reading a new block of * data). */ case SKIP: /* cur_zipfile_bufstart already takes account of extra_bytes, so don't * correct for it twice: */ ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes + (G.inptr-G.inbuf) + len) break; /* * Fourth case: assume we're at the start of an "extra field"; malloc * storage for it and read data into the allocated space. */ case EXTRA_FIELD: if (G.extra_field != (uch *)NULL) free(G.extra_field); if ((G.extra_field = (uch *)malloc(len)) == (uch *)NULL) { Info(slide, 0x401, ((char *)slide, LoadFarString(ExtraFieldTooLong), len)); /* cur_zipfile_bufstart already takes account of extra_bytes, * so don't correct for it twice: */ ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes + (G.inptr-G.inbuf) + len) } else if (readbuf(__G__ (char *)G.extra_field, len) == 0) return PK_EOF; break;#ifdef AMIGA /* * Fifth case, for the Amiga only: take the comment that would ordinarily * be skipped over, and turn it into a 79 character string that will be * attached to the file as a "filenote" after it is extracted. */ case FILENOTE: if ((extra_len = readbuf(__G__ tmp_fnote, (unsigned) MIN(len, 2 * AMIGA_FILENOTELEN - 1))) == 0) return PK_EOF; if ((len -= extra_len) > 0) /* treat remainder as in case SKIP: */ ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -