📄 gzip.c
字号:
crc = LG(buf);
bytes_out = LG(buf+4);
}
}
#endif /* RECORD_IO */
date = ctime((time_t*)&time_stamp) + 4; /* skip the day of the week */
date[12] = '\0'; /* suppress the 1/100sec and the year */
if (verbose) {
printf("%5s %08lx %11s ", methods[method], crc, date);
}
printf("%9ld %9ld ", bytes_in, bytes_out);
if (bytes_in == -1L) {
total_in = -1L;
bytes_in = bytes_out = header_bytes = 0;
} else if (total_in >= 0) {
total_in += bytes_in;
}
if (bytes_out == -1L) {
total_out = -1L;
bytes_in = bytes_out = header_bytes = 0;
} else if (total_out >= 0) {
total_out += bytes_out;
}
display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out, stdout);
printf(" %s\n", ofname);
}
/* ========================================================================
* Return true if the two stat structures correspond to the same file.
*/
local int same_file(stat1, stat2)
struct stat *stat1;
struct stat *stat2;
{
return stat1->st_ino == stat2->st_ino
&& stat1->st_dev == stat2->st_dev
#ifdef NO_ST_INO
/* Can't rely on st_ino and st_dev, use other fields: */
&& stat1->st_mode == stat2->st_mode
&& stat1->st_uid == stat2->st_uid
&& stat1->st_gid == stat2->st_gid
&& stat1->st_size == stat2->st_size
&& stat1->st_atime == stat2->st_atime
&& stat1->st_mtime == stat2->st_mtime
&& stat1->st_ctime == stat2->st_ctime
#endif
;
}
/* ========================================================================
* Return true if a file name is ambiguous because the operating system
* truncates file names.
*/
local int name_too_long(name, statb)
char *name; /* file name to check */
struct stat *statb; /* stat buf for this file name */
{
int s = strlen(name);
char c = name[s-1];
struct stat tstat; /* stat for truncated name */
int res;
tstat = *statb; /* Just in case OS does not fill all fields */
name[s-1] = '\0';
res = stat(name, &tstat) == 0 && same_file(statb, &tstat);
name[s-1] = c;
Trace((stderr, " too_long(%s) => %d\n", name, res));
return res;
}
/* ========================================================================
* Shorten the given name by one character, or replace a .tar extension
* with .tgz. Truncate the last part of the name which is longer than
* MIN_PART characters: 1234.678.012.gz -> 123.678.012.gz. If the name
* has only parts shorter than MIN_PART truncate the longest part.
* For decompression, just remove the last character of the name.
*
* IN assertion: for compression, the suffix of the given name is z_suffix.
*/
local void shorten_name(name)
char *name;
{
int len; /* length of name without z_suffix */
char *trunc = NULL; /* character to be truncated */
int plen; /* current part length */
int min_part = MIN_PART; /* current minimum part length */
char *p;
len = strlen(name);
if (decompress) {
if (len <= 1) error("name too short");
name[len-1] = '\0';
return;
}
p = get_suffix(name);
if (p == NULL) error("can't recover suffix\n");
*p = '\0';
save_orig_name = 1;
/* compress 1234567890.tar to 1234567890.tgz */
if (len > 4 && strequ(p-4, ".tar")) {
strcpy(p-4, ".tgz");
return;
}
/* Try keeping short extensions intact:
* 1234.678.012.gz -> 123.678.012.gz
*/
do {
p = strrchr(name, PATH_SEP);
p = p ? p+1 : name;
while (*p) {
plen = strcspn(p, PART_SEP);
p += plen;
if (plen > min_part) trunc = p-1;
if (*p) p++;
}
} while (trunc == NULL && --min_part != 0);
if (trunc != NULL) {
do {
trunc[0] = trunc[1];
} while (*trunc++);
trunc--;
} else {
trunc = strrchr(name, PART_SEP[0]);
if (trunc == NULL) error("internal error in shorten_name");
if (trunc[1] == '\0') trunc--; /* force truncation */
}
strcpy(trunc, z_suffix);
}
/* ========================================================================
* If compressing to a file, check if ofname is not ambiguous
* because the operating system truncates names. Otherwise, generate
* a new ofname and save the original name in the compressed file.
* If the compressed file already exists, ask for confirmation.
* The check for name truncation is made dynamically, because different
* file systems on the same OS might use different truncation rules (on SVR4
* s5 truncates to 14 chars and ufs does not truncate).
* This function returns -1 if the file must be skipped, and
* updates save_orig_name if necessary.
* IN assertions: save_orig_name is already set if ofname has been
* already truncated because of NO_MULTIPLE_DOTS. The input file has
* already been open and istat is set.
*/
local int check_ofname()
{
struct stat ostat; /* stat for ofname */
#ifdef ENAMETOOLONG
/* Check for strictly conforming Posix systems (which return ENAMETOOLONG
* instead of silently truncating filenames).
*/
errno = 0;
while (stat(ofname, &ostat) != 0) {
if (errno != ENAMETOOLONG) return 0; /* ofname does not exist */
shorten_name(ofname);
}
#else
if (stat(ofname, &ostat) != 0) return 0;
#endif
/* Check for name truncation on existing file. Do this even on systems
* defining ENAMETOOLONG, because on most systems the strict Posix
* behavior is disabled by default (silent name truncation allowed).
*/
if (!decompress && name_too_long(ofname, &ostat)) {
shorten_name(ofname);
if (stat(ofname, &ostat) != 0) return 0;
}
/* Check that the input and output files are different (could be
* the same by name truncation or links).
*/
if (same_file(&istat, &ostat)) {
if (strequ(ifname, ofname)) {
fprintf(stderr, "%s: %s: cannot %scompress onto itself\n",
progname, ifname, decompress ? "de" : "");
} else {
fprintf(stderr, "%s: %s and %s are the same file\n",
progname, ifname, ofname);
}
exit_code = ERROR;
return ERROR;
}
/* Ask permission to overwrite the existing file */
if (!force) {
char response[80];
strcpy(response,"n");
fprintf(stderr, "%s: %s already exists;", progname, ofname);
if (foreground && isatty(fileno(stdin))) {
fprintf(stderr, " do you wish to overwrite (y or n)? ");
fflush(stderr);
(void)fgets(response, sizeof(response)-1, stdin);
}
if (tolow(*response) != 'y') {
fprintf(stderr, "\tnot overwritten\n");
if (exit_code == OK) exit_code = WARNING;
return ERROR;
}
}
(void) chmod(ofname, 0777);
if (unlink(ofname)) {
fprintf(stderr, "%s: ", progname);
perror(ofname);
exit_code = ERROR;
return ERROR;
}
return OK;
}
#ifndef NO_UTIME
/* ========================================================================
* Set the access and modification times from the given stat buffer.
*/
local void reset_times (name, statb)
char *name;
struct stat *statb;
{
struct utimbuf timep;
/* Copy the time stamp */
timep.actime = statb->st_atime;
timep.modtime = statb->st_mtime;
/* Some systems (at least OS/2) do not support utime on directories */
if (utime(name, &timep) && !S_ISDIR(statb->st_mode)) {
WARN((stderr, "%s: ", progname));
if (!quiet) perror(ofname);
}
}
#endif
/* ========================================================================
* Copy modes, times, ownership from input file to output file.
* IN assertion: to_stdout is false.
*/
local void copy_stat(ifstat)
struct stat *ifstat;
{
#ifndef NO_UTIME
if (decompress && time_stamp != 0 && ifstat->st_mtime != time_stamp) {
ifstat->st_mtime = time_stamp;
if (verbose > 1) {
fprintf(stderr, "%s: time stamp restored\n", ofname);
}
}
reset_times(ofname, ifstat);
#endif
/* Copy the protection modes */
if (chmod(ofname, ifstat->st_mode & 07777)) {
WARN((stderr, "%s: ", progname));
if (!quiet) perror(ofname);
}
#ifndef NO_CHOWN
chown(ofname, ifstat->st_uid, ifstat->st_gid); /* Copy ownership */
#endif
remove_ofname = 0;
/* It's now safe to remove the input file: */
(void) chmod(ifname, 0777);
if (unlink(ifname)) {
WARN((stderr, "%s: ", progname));
if (!quiet) perror(ifname);
}
}
#ifndef NO_DIR
/* ========================================================================
* Recurse through the given directory. This code is taken from ncompress.
*/
local void treat_dir(dir)
char *dir;
{
dir_type *dp;
DIR *dirp;
char nbuf[MAX_PATH_LEN];
int len;
dirp = opendir(dir);
if (dirp == NULL) {
fprintf(stderr, "%s: %s unreadable\n", progname, dir);
exit_code = ERROR;
return ;
}
/*
** WARNING: the following algorithm could occasionally cause
** compress to produce error warnings of the form "<filename>.gz
** already has .gz suffix - ignored". This occurs when the
** .gz output file is inserted into the directory below
** readdir's current pointer.
** These warnings are harmless but annoying, so they are suppressed
** with option -r (except when -v is on). An alternative
** to allowing this would be to store the entire directory
** list in memory, then compress the entries in the stored
** list. Given the depth-first recursive algorithm used here,
** this could use up a tremendous amount of memory. I don't
** think it's worth it. -- Dave Mack
** (An other alternative might be two passes to avoid depth-first.)
*/
while ((dp = readdir(dirp)) != NULL) {
if (strequ(dp->d_name,".") || strequ(dp->d_name,"..")) {
continue;
}
len = strlen(dir);
if (len + NLENGTH(dp) + 1 < MAX_PATH_LEN - 1) {
strcpy(nbuf,dir);
if (len != 0 /* dir = "" means current dir on Amiga */
#ifdef PATH_SEP2
&& dir[len-1] != PATH_SEP2
#endif
#ifdef PATH_SEP3
&& dir[len-1] != PATH_SEP3
#endif
) {
nbuf[len++] = PATH_SEP;
}
strcpy(nbuf+len, dp->d_name);
treat_file(nbuf);
} else {
fprintf(stderr,"%s: %s/%s: pathname too long\n",
progname, dir, dp->d_name);
exit_code = ERROR;
}
}
closedir(dirp);
}
#endif /* ? NO_DIR */
/* ========================================================================
* Free all dynamically allocated variables and exit with the given code.
*/
extern void do_exit_dll();
local void do_exit(exitcode)
int exitcode;
{
//static int in_exit = 0;
//if (in_exit) exit(exitcode); comments -> FJ 01/03/99
//in_exit = 1;
if (env != NULL) free(env), env = NULL;
if (args != NULL) free((char*)args), args = NULL;
FREE(inbuf);
FREE(outbuf);
FREE(d_buf);
FREE(window);
#ifndef MAXSEG_64K
FREE(tab_prefix);
#else
FREE(tab_prefix0);
FREE(tab_prefix1);
#endif
//exit(exitcode);
do_exit_dll(exitcode); // DLL Implementation
}
/* ========================================================================
* Signal and error handler.
*/
RETSIGTYPE abort_gzip()
{
if (remove_ofname) {
close(ofd);
unlink (ofname);
}
do_exit(ERROR);
}
// DLL Implementation
int dozip( int inFile, int outFile )
{
bytes_in = 0;
return zip( inFile, outFile );
}
int dounzip( int inFile, int outFile )
{
int method;
if ( ( method = get_method( inFile ) ) < 0 )
return -1;
bytes_out=0;
if ( unzip( inFile, outFile ) != 0 )
return -1;
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -