📄 gzip.c
字号:
}#endif ilen = strlen(ifname); if (strequ(z_suffix, ".gz")) suf++; /* Search for all suffixes */ do { s = *suf;#ifdef NO_MULTIPLE_DOTS if (*s == '.') s++;#endif#ifdef MAX_EXT_CHARS strcpy(ifname, iname); /* Needed if the suffixes are not sorted by increasing length */ if (*dot == '\0') strcpy(dot, "."); dot[MAX_EXT_CHARS+1-strlen(s)] = '\0';#endif strcat(ifname, s); if (do_stat(ifname, sbuf) == 0) { DBGPrintfo(("get_istat(out4)\r\n")); return OK; } ifname[ilen] = '\0'; } while (*++suf != NULL); /* No suffix found, complain using z_suffix: */#ifdef MAX_EXT_CHARS strcpy(ifname, iname); if (*dot == '\0') strcpy(dot, "."); dot[MAX_EXT_CHARS+1-z_len] = '\0';#endif strcat(ifname, z_suffix); perror(ifname); exit_code = ERROR; DBGPrintfo(("get_istat(out5)\r\n")); return ERROR; }}/* ======================================================================== * Generate ofname given ifname. Return OK, or WARNING if file must be skipped. * Sets save_orig_name to true if the file name has been truncated. */local int make_ofname(){ DBGPrintfi(("make_ofname(In)\r\n")); { char *suff; /* ofname z suffix */ strcpy(ofname, ifname); /* strip a version number if any and get the gzip suffix if present: */ suff = get_suffix(ofname); if (decompress) { if (suff == NULL) { /* Whith -t or -l, try all files (even without .gz suffix) * except with -r (behave as with just -dr). */ if (!recursive && (list || test)) { DBGPrintfo(("make_ofname(out1)\r\n")); return OK; } /* Avoid annoying messages with -r */ if (verbose || (!recursive && !quiet)) { WARN((stderr,"%s: %s: unknown suffix -- ignored\n", progname, ifname)); } DBGPrintfo(("make_ofname(out2)\r\n")); return WARNING; } /* Make a special case for .tgz and .taz: */ strlwr(suff); if (strequ(suff, ".tgz") || strequ(suff, ".taz")) { strcpy(suff, ".tar"); } else { *suff = '\0'; /* strip the z suffix */ } /* 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; DBGPrintfo(("make_ofname(out3)\r\n")); return WARNING; } else { save_orig_name = 0;#ifdef NO_MULTIPLE_DOTS suff = strrchr(ofname, '.'); if (suff == NULL) { strcat(ofname, ".");# ifdef MAX_EXT_CHARS if (strequ(z_suffix, "z")) { strcat(ofname, "gz"); /* enough room */ DBGPrintfo(("make_ofname(out4)\r\n")); return OK; } /* 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. */ } else if (strlen(suff)-1 + z_len > MAX_SUFFIX) { suff[MAX_SUFFIX+1-z_len] = '\0'; save_orig_name = 1;# endif }#endif /* NO_MULTIPLE_DOTS */ strcat(ofname, z_suffix); } /* decompress ? */ DBGPrintfo(("make_ofname(out5)\r\n")); return OK; }}/* ======================================================================== * 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. * Updates time_stamp if there is one and --no-time is not used. * 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 */{ DBGPrintfi(("get_method(In)\r\n")); { uch flags; /* compression flags */ char magic[2]; /* magic header */ ulg stamp; /* time stamp */ /* If --force and --stdout, zcat == cat, so do not complain about * premature end of file: use try_byte instead of get_byte. */ if (force && to_stdout) { magic[0] = (char)try_byte(); magic[1] = (char)try_byte(); /* If try_byte returned EOF, magic[1] == 0xff */ } else { magic[0] = (char)get_byte(); magic[1] = (char)get_byte(); } method = -1; /* unknown yet */ part_nb++; /* number of parts in gzip file */ header_bytes = 0; 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) { method = (int)get_byte(); if (method != DEFLATED) { fprintf(stderr, "%s: %s: unknown method %d -- get newer version of gzip\n", progname, ifname, method); exit_code = ERROR; DBGPrintfo(("get_method(out1)\r\n")); return -1; } work = unzip; 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; DBGPrintfo(("get_method(out2)\r\n")); 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; } stamp = (ulg)get_byte(); stamp |= ((ulg)get_byte()) << 8; stamp |= ((ulg)get_byte()) << 16; stamp |= ((ulg)get_byte()) << 24; if (stamp != 0 && !no_time) time_stamp = stamp; (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 (no_name || (to_stdout && !list) || part_nb > 1) { /* Discard the old name */ char c; /* dummy used for NeXTstep 3.0 cc optimizer bug */ do {c=get_byte();} while (c != 0); } else { /* Copy the base name. Keep a directory prefix intact. */ char *p = basename(ofname); char *base = p; for (;;) { *p = (char)get_char(); if (*p++ == '\0') break; if (p >= ofname+sizeof(ofname)) { error("corrupted input -- file name too large"); return -1; } } /* If necessary, adapt the name to local OS conventions: */ if (!list) { MAKE_LEGAL_NAME(base); if (base) list=0; /* avoid warning about unused variable */ } } /* no_name || to_stdout */ } /* ORIG_NAME */ /* Discard file comment if any */ if ((flags & COMMENT) != 0) { while (get_char() != 0) /* null */ ; } if (part_nb == 1) { header_bytes = inptr + 2*sizeof(long); /* include crc and size */ } } else if (memcmp(magic, PKZIP_MAGIC, 2) == 0 && inptr == 2 && memcmp((char*)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) != OK) { DBGPrintfo(("get_method(out3)\r\n")); 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; } else if (memcmp(magic, LZH_MAGIC, 2) == 0) { work = unlzh; method = LZHED; last_member = 1; } else if (force && to_stdout && !list) { /* pass input unchanged */ method = STORED; work = copy; inptr = 0; last_member = 1; } if (method >= 0) { DBGPrintfo(("get_method(out4)\r\n")); return method; } if (part_nb == 1) { fprintf(stderr, "\n%s: %s: not in gzip format\n", progname, ifname); exit_code = ERROR; DBGPrintfo(("get_method(out5)\r\n")); return -1; } else { WARN((stderr, "\n%s: %s: decompression OK, trailing garbage ignored\n", progname, ifname)); DBGPrintfo(("get_method(out6)\r\n")); return -2; } } }/* ======================================================================== * 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 int do_list(ifd, method) int ifd; /* input file descriptor */ int method; /* compression method */{ DBGPrintfi(("do_list(In)\r\n")); { 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) { DBGPrintfo(("do_list(out10)\r\n")); return -1; } 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"); DBGPrintfo(("do_list(out1)\r\n")); return -1; } 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(); DBGPrintfo(("do_list(out11)\r\n")); return -1; } 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); } DBGPrintfo(("do_list(out)\r\n")); return 0;}/* ======================================================================== * Return true if the two stat structures correspond to the same file. */local int same_file(stat1, stat2) struct stat *stat1; struct stat *stat2;{ DBGPrintfi(("same_file(In)\r\n")); { DBGPrintfo(("same_file(out1)\r\n")); 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 ; }}/* ========================================================================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -