⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gzip.bak

📁 采用 LZ77 运算规则 压缩及解压工具
💻 BAK
📖 第 1 页 / 共 3 页
字号:
	    break;
	case 'v':
	    verbose++; break;
	case 'V':
	    version(); break;
	case 'Z':
#ifdef LZW
	    do_lzw = 1; break;
#else
	    fprintf(stderr, "-Z not supported in this version\n");
	    usage();
	    do_exit(ERROR); break;
#endif
	case '1':  case '2':  case '3':  case '4':
	case '5':  case '6':  case '7':  case '8':  case '9':
	    level = optc - '0';
	    break;
	default:
	    /* Error message already emitted by getopt_long. */
	    usage();
	    do_exit(ERROR);
	}
    } /* loop on all arguments */

    file_count = argc - optind;

    if (do_lzw && !decompress) work = lzw;

    /* Allocate all global buffers (for DYN_ALLOC option) */
    ALLOC(uch, inbuf,  INBUFSIZ +INBUF_EXTRA);
    ALLOC(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
    ALLOC(ush, d_buf,  DIST_BUFSIZE);
    ALLOC(uch, window, 2L*WSIZE);
#ifndef MAXSEG_64K
    ALLOC(ush, tab_prefix, 1L<<BITS);
#else
    ALLOC(ush, tab_prefix0, 1L<<(BITS-1));
    ALLOC(ush, tab_prefix1, 1L<<(BITS-1));
#endif

    /* And get to work */
    if (file_count != 0) {
	if (to_stdout && !test) {
	    SET_BINARY_MODE(fileno(stdout));
	}
	while (optind < argc) {
	    treat_file(argv[optind++]);
	}
    } else {  /* Standard input */
	treat_stdin();
    }
    do_exit(exit_code);
    return exit_code; /* just to avoid lint warning */
}

/* ========================================================================
 * Compress or decompress stdin
 */
local void treat_stdin()
{
    if (isatty(fileno((FILE *)(decompress ? stdin : stdout)))) {
	/* Do not send compressed data to the terminal or read it from
	 * the terminal. We get here when user invoked the program
	 * without parameters, so be helpful.
	 */
	fprintf(stderr,
	      "Compressed data not %s a terminal. Redirect %s file or pipe.\n",
		decompress ? "read from" : "written to",
		decompress ? "from" : "to");
	fprintf(stderr,"For help, type: %s -h\n", progname);
	do_exit(ERROR);
    }
    SET_BINARY_MODE(fileno(stdin));
    if (!test) SET_BINARY_MODE(fileno(stdout));

    strcpy(ifname, "stdin");
    strcpy(ofname, "stdout");

    /* Get the time stamp on the input file */
#ifdef NO_STDIN_FSTAT
    time_stamp = 0; /* time unknown */
#else
    if (fstat(fileno(stdin), &istat) != 0) {
	error("fstat(stdin)");
    } 
    time_stamp = istat.st_mtime;
#endif
    ifile_size = -1L; /* convention for unknown size */

    clear_bufs(); /* clear input and output buffers */
    to_stdout = 1;
    part_nb = 0;

    if (decompress) {
	method = get_method(ifd);
	if (method == -1) {
	    do_exit(exit_code); /* error message already emitted */
	}
    }

    /* Actually do the compression/decompression. Loop over zipped members.
     */
    for (;;) {
	(*work)(fileno(stdin), fileno(stdout));

	if (!decompress || last_member || inptr == insize) break;
	/* end of file */

	method = get_method(ifd);
	if (method == -1) return; /* error message already emitted */
	bytes_out = 0; /* required for length check */
    }

    if (verbose) {
	if (test) {
	    fprintf(stderr, " OK");

	} else if (!decompress) {
	    fprintf(stderr, "Compression: ");
	    display_ratio(bytes_in-bytes_out-overhead, bytes_in);
	}
	fprintf(stderr, "\n");
    }
}

/* ========================================================================
 * Compress or decompress the given file
 */
local void treat_file(iname)
    char *iname;
{
    /* Check if the input file is present, set ifname and istat: */
    if (get_istat(iname, &istat) != 0) return;

    /* If the input name is that of a directory, recurse or ignore: */
    if (S_ISDIR(istat.st_mode)) {
#ifndef NO_DIR
	if (recursive) {
	    treat_dir(iname);
	    /* Warning: ifname is now garbage */
	} else
#endif
	fprintf(stderr,"%s is a directory -- ignored\n", ifname);
	if (exit_code == OK) exit_code = WARNING;
	return;
    }
    if (!S_ISREG(istat.st_mode)) {
	fprintf(stderr,"%s is not a directory or a regular file - ignored\n",
		ifname);
	return;
    }
    if (istat.st_nlink > 1 && !to_stdout && !force) {
	fprintf(stderr, "%s has %d other link%c -- unchanged\n", ifname,
		(int)istat.st_nlink - 1, istat.st_nlink > 2 ? 's' : ' ');
	if (exit_code == OK) exit_code = WARNING;
	return;
    }

    ifile_size = istat.st_size;
    time_stamp = istat.st_mtime;

    /* Generate output file name */
    if (to_stdout) {
	strcpy(ofname, "stdout");

    } else if (make_ofname() != 0) {
	return;
    }

    /* Open the input file and determine compression method */
    ifd = open(ifname, O_RDONLY | O_BINARY);
    if (ifd == -1) {
	perror(ifname);
	exit_code = ERROR;
	return;
    }
    clear_bufs(); /* clear input and output buffers */
    part_nb = 0;

    if (decompress) {
	method = get_method(ifd); /* updates ofname if original given */
	if (method == -1) return; /* error message already emitted */
    }

    /* If compressing to a file, check if ofname is not ambigous
     * because the operating system truncates names. Otherwise, generate
     * a new ofname and save the original name in the compressed file.
     */
    if (to_stdout) {
	ofd = fileno(stdout);
	/* keep remove_ofname as zero */
    } else {
	if (create_outfile() == -1) return;

	if (save_orig_name && !verbose && !force) {
	    fprintf(stderr, "%s compressed to %s\n", ifname, ofname);
	}
    }
    if (verbose) {
	fprintf(stderr, "%s:\t%s", ifname, (int)strlen(ifname) >= 15 ? 
		"" : ((int)strlen(ifname) >= 7 ? "\t" : "\t\t"));
    }

    /* Actually do the compression/decompression. If testing only and
     * input file is in LZW format (which has no CRC) skip it. Loop over
     * zipped members.
     */
    for (;;) {
	(*work)(ifd, ofd);

	if (!decompress || last_member || inptr == insize) break;
	/* end of file */

	method = get_method(ifd);
	if (method == -1) break; /* error message already emitted */
	bytes_out = 0; /* required for length check */
    }

    close(ifd);
    if (!to_stdout && close(ofd)) {
	write_error();
    }
    if (method == -1) return;

    /* Display statistics */
    if(verbose) {
	if (!decompress) {
	    display_ratio(bytes_in-bytes_out-overhead, bytes_in);
	}
	if (test) {
	    fprintf(stderr, " OK");
	} else if (!to_stdout) {
	    fprintf(stderr, " -- replaced with %s", ofname);
	}
	fprintf(stderr, "\n");
    }
    /* Copy modes, times, ownership */
    if (!to_stdout) {
	copy_stat(&istat);
    }
}

/* ========================================================================
 * Create the output file. Try twice if ofname is exactly one beyond the
 * name limit, to avoid creating a compressed file of name "1234567890123."
 * We could actually loop more than once if the user gives an extra long
 * name, but I prefer generating an error then. (Posix forbids the system
 * to truncate names.) The error message is generated by check_ofname()
 * in this case.
 * IN assertion: the input file has already been open (ifd is set) and
 * ofname has already been updated if there was an original name.
 */
local int create_outfile()
{
    struct stat ostat; /* stat for ofname */
    int n;             /* loop counter */

    for (n = 1; n <= 2; n++) {
	if (check_ofname() == -1) {
	    close(ifd);
	    return -1;
	}
	/* Create the output file */
	remove_ofname = 1;
	ofd = open(ofname, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, RW_USER);
	if (ofd == -1) {
	    perror(ofname);
	    close(ifd);
	    exit_code = ERROR;
	    return -1;
	}

	/* Check for name truncation on new file (1234567890123.z) */
	if (fstat(ofd, &ostat) != 0) {
	    perror(ofname);
	    fprintf(stderr, " fstat failed\n");
	    close(ifd); close(ofd);
	    unlink(ofname);
	    exit_code = ERROR;
	    return -1;
	}
	if (!name_too_long(ofname, &ostat)) return 0;

	if (decompress) {
	    /* name might be too long if an original name was saved */
	    fprintf(stderr, " warning, name truncated: %s\n", ofname);
	    return 0;
	} else {
#ifdef NO_MULTIPLE_DOTS
	    /* Should never happen, see check_ofname() */
	    fprintf(stderr, "ERROR: name too long: %s\n", ofname);
	    do_exit(ERROR);
#else
	    close(ofd);
	    unlink(ofname);
	    save_orig_name = 1;
	    strcpy(ofname+strlen(ofname)-3, ".z");
	    /* 1234567890123.z -> 123456789012.z */
#endif
	} /* decompress ? */
    } /* for (n) */

    close(ifd);
    fprintf(stderr, " name too long: %s\n", ofname);
    exit_code = ERROR;
    return -1;
}

/* ========================================================================
 * Use lstat if available, except for -c or -f. Use stat otherwise.
 * This allows links when not removing the original file.
 */
local int do_stat(name, sbuf)
    char *name;
    struct stat *sbuf;
{
#if (defined(S_IFLNK) || defined (S_ISLNK)) && !defined(NO_SYMLINK)
    if (!to_stdout && !force) {
	return lstat(name, sbuf);
    }
#endif
    return stat(name, sbuf);
}

/* ========================================================================
 * Set ifname to the input file name (with .z appended if necessary)
 * and istat to its stats. Return 0 if ok, -1 if error.
 */
local int get_istat(iname, sbuf)
    char *iname;
    struct stat *sbuf;
{
    int iexists; /* set if iname exists */
    int ilen = strlen(iname);

    strcpy(ifname, iname);
    errno = 0;

    /* If input file exists, return OK. */
    if (do_stat(ifname, sbuf) == 0) return 0;

    if (!decompress || errno != ENOENT) {
	perror(ifname);
	exit_code = ERROR;
	return -1;
    }
    /* file.ext doesn't exist, try file.ext.z and file.ext.Z (or file.extz) */
    if (ilen < 3 || (strcmp(ifname + ilen - 2, ".Z") != 0
		  && strcmp(ifname + ilen - 2, ".z") != 0)) {
#ifdef NO_MULTIPLE_DOTS
	if (strrchr(ifname, '.') != NULL) {
	   strcat(ifname, "z"), ilen += 1;
	} else
#endif
	strcat(ifname, ".z"), ilen += 2;
	errno = 0;
	iexists = !do_stat(ifname, sbuf);
	if (!iexists) {
	    errno = 0;
	    ifname[ilen-1] = 'Z';
	    iexists = !do_stat(ifname, sbuf);
	}
#ifdef NO_MULTIPLE_DOTS
	/* One more try just to be nice to you */
	if (!iexists) {
	    char c = ifname[ilen-2];
	    errno = 0;
	    strcpy(ifname+ilen-2, "z");
	    iexists = !do_stat(ifname, sbuf);
	    if (!iexists) {
		ifname[ilen-2] = c;
	    }
	}
#endif
	if (!iexists) {
	    ifname[ilen-1] = 'z';
	    perror(ifname);
	    exit_code = ERROR;
	    return -1;
	}
	if (!S_ISREG (sbuf->st_mode)) {
	    fprintf(stderr, "%s: Not a regular file -- ignored\n", ifname);
	    if (exit_code == OK) exit_code = WARNING;
	    return -1;
	}
	return 0; /* ok */
    } /* try file.z */

    perror(ifname); /* ifname and ifname.z do not exist */
    exit_code = ERROR;
    return -1;
}

/* ========================================================================
 * Generate ofname given ifname. Return 0 if ok, -1 if file must be skipped.
 * Initializes save_orig_name.
 */
local int make_ofname()
{
    int iflen = strlen(ifname);
#ifdef NO_MULTIPLE_DOTS
    int z_suffix = iflen > 2 && tolow(ifname[iflen-1]) == 'z';
#else
    int z_suffix = iflen > 2 && (strcmp(ifname+iflen-2, ".z") == 0
			  || strcmp(ifname+iflen-2, ".Z") == 0);
#endif
    int zip_suffix = iflen > 4 && (strcmp(ifname+iflen-4, ".zip") == 0
			  || strcmp(ifname+iflen-4, ".ZIP") == 0);

    if (decompress) {
	/* Be tolerant for "zcat foo.tar-z | tar xf -" but do not
	 * complain for "gunzip -r *". In other words, force .z suffix
	 * for gunzip but not zcat.
	 */
	if (!to_stdout && !z_suffix && !zip_suffix) {
	    if (verbose) {
		fprintf(stderr,"%s -- no z suffix, ignored\n", ifname);
	    }
	    return -1;
	}
	strcpy(ofname, ifname);
	if (z_suffix) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -