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

📄 gzip.c

📁 GNU 系统开发的基于Iz77语法的压缩 学习lz77压缩算法 
💻 C
📖 第 1 页 / 共 3 页
字号:
	    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. However, on systems supporting         * pseudo ttys, let the beginner stare at the 'hung' program	 * (explicity request from Noah Friedman). Don't give an error message	 * if the user only wanted the version number (gzip -V).	 */	if (quit_on_tty) do_exit(OK);#ifdef NO_PTY	fprintf(stderr,	  "%s: compressed data not %s a terminal. Redirect %s file or pipe.\n",		progname, decompress ? "read from" : "written to",		decompress ? "from" : "to");	fprintf(stderr,"For help, type: %s -h\n", progname);	do_exit(ERROR);#endif    }    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 < 0) {	    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) {	    struct stat st;	    st = istat;	    treat_dir(iname);	    /* Warning: ifname is now garbage */	    reset_times (iname, &st);	} else#endif	WARN((stderr,"%s: %s is a directory -- ignored\n", progname, ifname));	return;    }    if (!S_ISREG(istat.st_mode)) {	WARN((stderr,	      "%s: %s is not a directory or a regular file - ignored\n",	      progname, ifname));	return;    }    if (istat.st_nlink > 1 && !to_stdout && !force) {	WARN((stderr, "%s: %s has %d other link%c -- unchanged\n",	      progname, ifname,	      (int)istat.st_nlink - 1, istat.st_nlink > 2 ? 's' : ' '));	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. The mode     * parameter is ignored but required by some systems (VMS).     */    ifd = open(ifname, O_RDONLY | O_BINARY, RW_USER);    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 < 0) {	    close(ifd);	    return;               /* error message already emitted */	}    }    /* 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 (to_stdout) {	ofd = fileno(stdout);	/* keep remove_ofname as zero */    } else {	if (create_outfile() == -1) return;	if (save_orig_name && !verbose && !quiet) {	    fprintf(stderr, "%s: %s compressed to %s\n",		    progname, 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. Loop over zipped members.     */    for (;;) {	(*work)(ifd, ofd);	if (!decompress || last_member || inptr == insize) break;	/* end of file */	method = get_method(ifd);	if (method < 0) 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;     /* error, don't display success msg */    /* 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. Return 0 for success, -1 for error. * 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 assertions: the input file has already been open (ifd is set) and *   ofname has already been updated if there was an original name. * OUT assertions: ifd and ofd are closed in case of error. */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) {	    fprintf(stderr, "%s: ", progname);	    perror(ofname);	    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 */	    WARN((stderr, "%s: %s: warning, name truncated\n",		  progname, ofname));	    return 0;	} else {#ifdef NO_MULTIPLE_DOTS	    /* Should never happen, see check_ofname() */	    fprintf(stderr, "%s: %s: name too long\n", progname, ofname);	    do_exit(ERROR);#else	    close(ofd);	    unlink(ofname);	    save_orig_name = 1;	    strcpy(ofname+strlen(ofname)-Z_LEN-1, Z_SUFFIX);            /* 1234567890123.z -> 123456789012.z */#endif	} /* decompress ? */    } /* for (n) */    close(ifd);    fprintf(stderr, "%s: %s: name too long\n", progname, 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);}/* ======================================================================== * Return a pointer to the 'z' suffix of a file name, or NULL. * For all systems, ".z", ".Z", ".taz", ".tgz", "-z" are accepted suffixes. * ".tgz" is a useful convention for tar.z files on systems limited * to 3 characters extensions. On such systems, ".?z" and ".??z" are * also accepted suffixes. For Unix, we do not want to accept any * .??z suffix as indicating a compressed file; some people use .xyz * to denote volume data. */local char *get_suffix(name)    char *name;{    int len;    char *p = strrchr(name, '.');    char suffix[10];       /* last few chars of name, forced to lower case */    if (p == NULL || p == name || strchr(p-1, PATH_SEP) != NULL) return NULL;    strncpy(suffix, p, sizeof(suffix));    suffix[sizeof(suffix)-1] = '\0';    /* Force null termination */#ifdef SUFFIX_SEP    /* strip a version number from the file name */    {	char *v = strrchr(suffix, SUFFIX_SEP);	if (v != NULL) *v = '\0';    }#endif    strlwr(suffix);    if (strequ(suffix, ".z") || strequ(suffix, ".zip")	|| strequ(suffix, ".tgz") || strequ(suffix, ".taz")) {	return p;    }    len = strlen(suffix);    if (len <= 2) return NULL;    if (strequ(suffix+len-2, "-z")) return p+len-2;#ifdef MAX_EXT_CHARS    if (suffix[len-1] == 'z') return p+len-1;#endif    return NULL;}/* ======================================================================== * 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);    char *suff;    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. For MSDOS     * try file.exz, for VMS try file.ext-z.     */    suff = get_suffix(ifname);    if (suff != NULL) {	perror(ifname); /* ifname already has z suffix and does not exist */	exit_code = ERROR;	return -1;    }#ifdef SUFFIX_SEP    /* strip a version number from the input file name */    if ((suff = strrchr(ifname, SUFFIX_SEP)) != NULL) *suff = '\0';#endif    if (strrchr(ifname, '.') != NULL) {       strcat(ifname, Z_SUFFIX);       ilen += Z_LEN;    } else {       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)) {	WARN((stderr, "%s: %s: not a regular file -- ignored\n",	      progname, ifname));	return -1;    }    return 0; /* ok */}/* ======================================================================== * Generate ofname given ifname. Return 0 if ok, -1 if file must be skipped. * Initializes save_orig_name. * IN assertion: this function is not called if to_stdout is true. */local int make_ofname(){

⌨️ 快捷键说明

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