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

📄 gzip.c

📁 GZip Compress Souce Code
💻 C
📖 第 1 页 / 共 5 页
字号:
 * 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 */{  DBGPrintfi(("name_too_long(In)\r\n"));  {    int s = (int)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));        DBGPrintfo(("name_too_long(out1)\r\n"));    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 int shorten_name(name)    char *name;{  DBGPrintfi(("shorten_name(In)\r\n"));  {    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 = (int)strlen(name);    if (decompress) {		if (len <= 1) 		{			error("name too short");			DBGPrintfo(("shorten_name(out10)\r\n"));			return -1;		}		name[len-1] = '\0';				DBGPrintfo(("shorten_name(out1)\r\n"));		return 0;    }    p = get_suffix(name);    if (p == NULL) 	{		error("can't recover suffix\n");		DBGPrintfo(("shorten_name(out11)\r\n"));		return -1;	}    *p = '\0';    save_orig_name = 1;    /* compress 1234567890.tar to 1234567890.tgz */    if (len > 4 && strequ(p-4, ".tar")) {		strcpy(p-4, ".tgz");				DBGPrintfo(("shorten_name(out2)\r\n"));		return 0;    }    /* 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 = (int)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");		DBGPrintfo(("shorten_name(out3)\r\n"));		return -1;	}	if (trunc[1] == '\0') trunc--; /* force truncation */    }    strcpy(trunc, z_suffix);  }  DBGPrintfo(("shorten_name(out)\r\n"));  return 0;}/* ======================================================================== * 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(){  DBGPrintfi(("check_ofname(In)\r\n"));  {    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) {                                     DBGPrintfo(("check_ofname(out1)\r\n"));                                    return  0;                                    } /* ofname does not exist */		if ( shorten_name(ofname) < 0 )		{			DBGPrintfo(("check_ofname(out11)\r\n"));			return ERROR;		}    }#else    if (stat(ofname, &ostat) != 0) {                                     DBGPrintfo(("check_ofname(out2)\r\n"));                                    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)) {		if ( shorten_name(ofname) < 0 )		{			DBGPrintfo(("check_ofname(out30)\r\n"));			return  -1;		}		if (stat(ofname, &ostat) != 0) {                                		 DBGPrintfo(("check_ofname(out3)\r\n"));                               		 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;		DBGPrintfo(("check_ofname(out4)\r\n"));	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;	        	DBGPrintfo(("check_ofname(out5)\r\n"));    	return  ERROR;	}    }    (void) chmod(ofname, 0777);    if (unlink(ofname)) {	fprintf(stderr, "%s: ", progname);	perror(ofname);	exit_code = ERROR;		DBGPrintfo(("check_ofname(out6)\r\n"));	return  ERROR;    }    DBGPrintfo(("check_ofname(out7)\r\n"));    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;{  DBGPrintfi(("reset_times(In)\r\n"));  {    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);    }  }  DBGPrintfo(("reset_times(out)\r\n"));}#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;{  DBGPrintfi(("copy_stat(In)\r\n"));  {#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);    }  }  DBGPrintfo(("copy_stat(out)\r\n"));}#ifndef NO_DIR/* ======================================================================== * Recurse through the given directory. This code is taken from ncompress. */local void treat_dir(dir)    char *dir;{  DBGPrintfi(("treat_dir(In)\r\n"));  {    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;		DBGPrintfo(("treat_dir(out1)\r\n"));	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);  }  DBGPrintfo(("treat_dir(out)\r\n"));}#endif /* ? NO_DIR *//* ======================================================================== * Free all dynamically allocated variables and exit with the given code. */extern void TPEG_free(void * mem);int in_exit = 0;local void do_exit(exitcode)    int exitcode;{  DBGPrintfi(("do_exit(In)\r\n"));  {    if (in_exit) 	{		DBGPrintfo(("do_exit(out1)\r\n"));		return;	}    in_exit = 1;	if (env != NULL)  TPEG_free(env),  env  = NULL;	if (args != NULL) TPEG_free((char*)args), args = NULL;//    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);  }  DBGPrintfo(("do_exit(out)\r\n"));}#if 0local void do_exit(exitcode)    int exitcode;{  DBGPrintfi(("do_exit(In)\r\n"));  {    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);  }  DBGPrintfo(("do_exit(out)\r\n"));}#endif/* ======================================================================== * Signal and error handler. */// by bskimRETSIGTYPE abort_gzip(){  DBGPrintfi(("abort_gzip(In)\r\n"));  {//   if (remove_ofname) {//       close(ofd);//       unlink (ofname);//   }   do_exit(ERROR);  }  DBGPrintfo(("abort_gzip(Out)\r\n"));}#if 0RETSIGTYPE abort_gzip(){  DBGPrintfi(("abort_gzip(In)\r\n"));  {   if (remove_ofname) {       close(ofd);       unlink (ofname);   }   do_exit(ERROR);  }}#endif

⌨️ 快捷键说明

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