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

📄 gzip.c

📁 一些关于HTTP协议处理的文档,还包括了gzip包(它是用来解压缩HTTP传送的压缩数据)
💻 C
📖 第 1 页 / 共 4 页
字号:
}/* ======================================================================== * Display the characteristics of the compressed file. * If the given method is < 0, display the accumulated totals. * IN assertions: time_stamp, header_bytes and ifile_size are initialized. */local void do_list(ifd, method)    int ifd;     /* input file descriptor */    int method;  /* compression method */{    ulg crc;  /* original crc */    static int first_time = 1;    static char* methods[MAX_METHODS] = {        "store",  /* 0 */        "compr",  /* 1 */        "pack ",  /* 2 */        "lzh  ",  /* 3 */        "", "", "", "", /* 4 to 7 reserved */        "defla"}; /* 8 */    char *date;    if (first_time && method >= 0) {	first_time = 0;	if (verbose)  {	    printf("method  crc     date  time  ");	}	if (!quiet) {	    printf("compressed  uncompr. ratio uncompressed_name\n");	}    } else if (method < 0) {	if (total_in <= 0 || total_out <= 0) return;	if (verbose) {	    printf("                            %9lu %9lu ",		   total_in, total_out);	} else if (!quiet) {	    printf("%9ld %9ld ", total_in, total_out);	}	display_ratio(total_out-(total_in-header_bytes), total_out, stdout);	/* header_bytes is not meaningful but used to ensure the same	 * ratio if there is a single file.	 */	printf(" (totals)\n");	return;    }    crc = (ulg)~0; /* unknown */    bytes_out = -1L;    bytes_in = ifile_size;#if RECORD_IO == 0    if (method == DEFLATED && !last_member) {        /* Get the crc and uncompressed size for gzip'ed (not zip'ed) files.         * If the lseek fails, we could use read() to get to the end, but         * --list is used to get quick results.         * Use "gunzip < foo.gz | wc -c" to get the uncompressed size if         * you are not concerned about speed.         */        bytes_in = (long)lseek(ifd, (off_t)(-8), SEEK_END);        if (bytes_in != -1L) {            uch buf[8];            bytes_in += 8L;            if (read(ifd, (char*)buf, sizeof(buf)) != sizeof(buf)) {                read_error();            }            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. */local void do_exit(exitcode)    int exitcode;{    static int in_exit = 0;    if (in_exit) exit(exitcode);    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);}/* ======================================================================== * Signal and error handler. */RETSIGTYPE abort_gzip(){   if (remove_ofname) {       close(ofd);       unlink (ofname);   }   do_exit(ERROR);}

⌨️ 快捷键说明

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