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

📄 gzip.c

📁 GNU 系统开发的基于Iz77语法的压缩 学习lz77压缩算法 
💻 C
📖 第 1 页 / 共 3 页
字号:
    char *suff;            /* ofname z suffix */    strcpy(ofname, ifname);    suff = get_suffix(ofname);    if (decompress) {	if (suff == NULL) {	    WARN((stderr,"%s: %s: no z suffix -- ignored\n",		  progname, ifname));	    return -1;	}	/* Make a special case for .tgz and .taz: */	strlwr(suff);	if (strequ(suff, ".tgz") || strequ(suff, ".taz")) {	    strcpy(suff, ".tar");	} else {	    *suff = '\0'; /* strip z suffix and optional version number */	}        /* ofname might be changed later if infile contains an original name */    } else if (suff != NULL) {	/* Avoid annoying messages with -r (see treat_dir()) */	if (verbose || (!recursive && !quiet)) {	    fprintf(stderr, "%s: %s already has %s suffix -- unchanged\n",		    progname, ifname, suff);	}	if (exit_code == OK) exit_code = WARNING;	return -1;    } else {        save_orig_name = 0;#ifdef SUFFIX_SEP	/* strip a version number from the file name */	if ((suff = strrchr(ofname, SUFFIX_SEP)) != NULL) *suff = '\0';#endif#ifdef NO_MULTIPLE_DOTS	suff = strrchr(ofname, '.');	if (suff != NULL) {#  ifdef MAX_EXT_CHARS	    /* On the Atari and some versions of MSDOS, name_too_long()	     * does not work correctly because of a bug in stat(). So we	     * must truncate here.	     */	    if (strlen(suff) > MAX_EXT_CHARS) {		strcpy(suff + MAX_EXT_CHARS, do_lzw ? "Z" : "z");		save_orig_name = 1;		return 0;	    }#  endif	    strcat(ofname, Z_SUFFIX);	    return 0;	}#endif	strcat(ofname, do_lzw ? ".Z" : ".z");    } /* decompress ? */    return 0;}/* ======================================================================== * Check the magic number of the input file and update ofname if an * original name was given and to_stdout is not set. * Return the compression method, -1 for error, -2 for warning. * Set inptr to the offset of the next byte to be processed. * This function may be called repeatedly for an input file consisting * of several contiguous gzip'ed members. * IN assertions: there is at least one remaining compressed member. *   If the member is a zip file, it must be the only one. */local int get_method(in)    int in;        /* input file descriptor */{    uch flags;    char magic[2]; /* magic header */    magic[0] = (char)get_byte();    magic[1] = (char)get_byte();    time_stamp = istat.st_mtime; /* may be modified later for some methods */    method = -1;                 /* unknown yet */    part_nb++;                   /* number of parts in gzip file */    last_member = RECORD_IO;    /* assume multiple members in gzip file except for record oriented I/O */    if (memcmp(magic, GZIP_MAGIC, 2) == 0        || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) {	work = unzip;	method = (int)get_byte();	flags  = (uch)get_byte();	if ((flags & ENCRYPTED) != 0) {	    fprintf(stderr,		    "%s: %s is encrypted -- get newer version of gzip\n",		    progname, ifname);	    exit_code = ERROR;	    return -1;	}	if ((flags & CONTINUATION) != 0) {	    fprintf(stderr,	   "%s: %s is a a multi-part gzip file -- get newer version of gzip\n",		    progname, ifname);	    exit_code = ERROR;	    if (force <= 1) return -1;	}	if ((flags & RESERVED) != 0) {	    fprintf(stderr,		    "%s: %s has flags 0x%x -- get newer version of gzip\n",		    progname, ifname, flags);	    exit_code = ERROR;	    if (force <= 1) return -1;	}	time_stamp  = (ulg)get_byte();	time_stamp |= ((ulg)get_byte()) << 8;	time_stamp |= ((ulg)get_byte()) << 16;	time_stamp |= ((ulg)get_byte()) << 24;	(void)get_byte();  /* Ignore extra flags for the moment */	(void)get_byte();  /* Ignore OS type for the moment */	if ((flags & CONTINUATION) != 0) {	    unsigned part = (unsigned)get_byte();	    part |= ((unsigned)get_byte())<<8;	    if (verbose) {		fprintf(stderr,"%s: %s: part number %u\n",			progname, ifname, part);	    }	}	if ((flags & EXTRA_FIELD) != 0) {	    unsigned len = (unsigned)get_byte();	    len |= ((unsigned)get_byte())<<8;	    if (verbose) {		fprintf(stderr,"%s: %s: extra field of %u bytes ignored\n",			progname, ifname, len);	    }	    while (len--) (void)get_byte();	}	/* Get original file name if it was truncated */	if ((flags & ORIG_NAME) != 0) {	    if (to_stdout || part_nb > 1) {		/* Discard the old name */		while (get_byte() != 0) /* null */ ;	    } else {		/* Copy the base name. Keep a directory prefix intact. */		char *p = basename(ofname);		for (;;) {		    *p = (char)get_byte();		    if (*p++ == '\0') break;		    if (p >= ofname+sizeof(ofname)) {			error("corrupted input -- file name too large");		    }		}	    } /* to_stdout */	} /* orig_name */	/* Discard file comment if any */	if ((flags & COMMENT) != 0) {	    while (get_byte() != 0) /* null */ ;	}    } else if (memcmp(magic, PKZIP_MAGIC, 2) == 0 && inptr == 2	    && memcmp(inbuf, PKZIP_MAGIC, 4) == 0) {	/* To simplify the code, we support a zip file when alone only.         * We are thus guaranteed that the entire local header fits in inbuf.         */        inptr = 0;	work = unzip;	if (check_zipfile(in) == -1) return -1;	/* check_zipfile may get ofname from the local header */	last_member = 1;    } else if (memcmp(magic, PACK_MAGIC, 2) == 0) {	work = unpack;	method = PACKED;    } else if (memcmp(magic, LZW_MAGIC, 2) == 0) {	work = unlzw;	method = COMPRESSED;	last_member = 1;    }    if (method >= 0) return method;    if (part_nb == 1) {	fprintf(stderr, "%s: %s is not in gzip format\n", progname, ifname);	exit_code = ERROR;	return -1;    } else {	WARN((stderr, "%s: %s: trailing garbage ignored\n", progname, ifname));	return -2;    }}/* ======================================================================== * 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_mode  == stat2->st_mode	&& stat1->st_ino   == stat2->st_ino	&& stat1->st_dev   == stat2->st_dev	&& 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;}/* ======================================================================== * 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;    return res;}/* ======================================================================== * 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 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(){    int s = strlen(ofname);    struct stat	ostat; /* stat for ofname */    if (stat(ofname, &ostat) != 0) return 0;    /* Check for name truncation on existing file: */#ifdef NO_MULTIPLE_DOTS    if (!decompress && name_too_long(ofname, &ostat)) {#else    if (!decompress && s > 8 && name_too_long(ofname, &ostat)) {#endif	save_orig_name = 1;#ifdef NO_MULTIPLE_DOTS	strcpy(ofname+s-Z_LEN-1, Z_SUFFIX);  /* f.extz -> f.exz  */#else	strcpy(ofname+s-4, ".z"); /* 12345678901234.z -> 123456789012.z */#endif	if (stat(ofname, &ostat) != 0) return 0;    } /* !decompress && name_too_long */    /* Check that the input and output files are different (could be     * the same by name truncation or links).     */    if (same_file(&istat, &ostat)) {	fprintf(stderr, "%s: %s and %s are the same file\n",		progname, ifname, ofname);	exit_code = ERROR;	return -1;    }    /* 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)read(fileno(stdin), response, sizeof(response));	}	if (tolow(*response) != 'y') {	    fprintf(stderr, "\tnot overwritten\n");	    if (exit_code == OK) exit_code = WARNING;	    return -1;	}    }    (void) chmod(ofname, 0777);    if (unlink(ofname)) {	fprintf(stderr, "%s: ", progname);	perror(ofname);	exit_code = ERROR;	return -1;    }    return 0;}/* ======================================================================== * Set the access and modification times from the given stat buffer. */local void reset_times (name, statb)    char *name;    struct stat *statb;{#ifndef NO_UTIME    struct utimbuf	timep;    /* Copy the time stamp */    timep.actime  = statb->st_atime;    timep.modtime = statb->st_mtime;    if (utime(name, &timep)) {	WARN((stderr, "%s: ", progname));	if (!quiet) perror(ofname);    }#else    name = name; statb = statb; /* avoid warnings */#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    time_t diff = ifstat->st_mtime - time_stamp;    if (diff < 0) diff = -diff;    if (decompress && diff > 60 && time_stamp != 0) {	ifstat->st_mtime = time_stamp;	if (verbose) {	    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];    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>.z     ** already has .z suffix - ignored". This occurs when the     ** .z 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;	}	if (((int)strlen(dir) + NLENGTH(dp) + 1) < (MAX_PATH_LEN - 1)) {	    strcpy(nbuf,dir);	    if (strlen(dir) != 0) { /* dir = "" means current dir on Amiga */#ifdef OTHER_PATH_SEP		if (dir[strlen(dir)-1] != OTHER_PATH_SEP)#endif		strcat(nbuf,"/");	    }	    strcat(nbuf,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;{    if (env != NULL)  free(env),  env  = NULL;    if (args != NULL) free(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 + -