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

📄 zipnote.c

📁 给出了 zip 压缩算法的完整实现过程。
💻 C
字号:
/*  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.  See the accompanying file LICENSE, version 2005-Feb-10 or later  (the contents of which are also included in zip.h) for terms of use.  If, for some reason, all these files are missing, the Info-ZIP license  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html*//* *  zipnote.c by Mark Adler. */#define __ZIPNOTE_C#ifndef UTIL#define UTIL#endif#include "zip.h"#define DEFCPYRT        /* main module: enable copyright string defines! */#include "revision.h"#include <signal.h>/* Calculate size of static line buffer used in write (-w) mode. */#define WRBUFSIZ 2047/* The line buffer size should be at least as large as FNMAX. */#if FNMAX > WRBUFSIZ#  undef WRBUFSIZ#  define WRBUFSIZ FNMAX#endif/* Character to mark zip entry names in the comment file */#define MARK '@'#define MARKE " (comment above this line)"#define MARKZ " (zip file comment below this line)"/* Temporary zip file name and file pointer */local char *tempzip;local FILE *tempzf;/* Local functions */local void handler OF((int));local void license OF((void));local void help OF((void));local void version_info OF((void));local void putclean OF((char *, extent));/* getline name conflicts with GNU getline() function */local char *zgetline OF((char *, extent));local int catalloc OF((char * far *, char *));int main OF((int, char **));#ifdef MACOS#define ziperr(c, h)    zipnoteerr(c, h)#define zipwarn(a, b)   zipnotewarn(a, b)void zipnoteerr(int c, ZCONST char *h);void zipnotewarn(ZCONST char *a, ZCONST char *b);#endif#ifdef QDOS#define exit(p1) QDOSexit()#endifvoid ziperr(c, h)int c;                  /* error code from the ZE_ class */ZCONST char *h;         /* message about how it happened *//* Issue a message for the error, clean up files and memory, and exit. */{  if (PERR(c))    perror("zipnote error");  fprintf(stderr, "zipnote error: %s (%s)\n", ziperrors[c-1], h);  if (tempzf != NULL)    fclose(tempzf);  if (tempzip != NULL)  {    destroy(tempzip);    free((zvoid *)tempzip);  }  if (zipfile != NULL)    free((zvoid *)zipfile);  EXIT(c);}local void handler(s)int s;                  /* signal number (ignored) *//* Upon getting a user interrupt, abort cleanly using ziperr(). */{#ifndef MSDOS  putc('\n', stderr);#endif /* !MSDOS */  ziperr(ZE_ABORT, "aborting");  s++;                                  /* keep some compilers happy */}void zipwarn(a, b)ZCONST char *a, *b;     /* message strings juxtaposed in output *//* Print a warning message to stderr and return. */{  fprintf(stderr, "zipnote warning: %s%s\n", a, b);}local void license()/* Print license information to stdout. */{  extent i;             /* counter for copyright array */  for (i = 0; i < sizeof(swlicense)/sizeof(char *); i++)    puts(swlicense[i]);}local void help()/* Print help (along with license info) to stdout. */{  extent i;             /* counter for help array */  /* help array */  static ZCONST char *text[] = {"","ZipNote %s (%s)",#ifdef VM_CMS"Usage:  zipnote [-w] [-q] [-b fm] zipfile",#else"Usage:  zipnote [-w] [-q] [-b path] zipfile",#endif"  the default action is to write the comments in zipfile to stdout","  -w   write the zipfile comments from stdin",#ifdef VM_CMS"  -b   use \"fm\" as the filemode for the temporary zip file",#else"  -b   use \"path\" for the temporary zip file",#endif"  -q   quieter operation, suppress some informational messages","  -h   show this help    -v   show version info    -L   show software license","","Example:",#ifdef VMS"     define/user sys$output foo.tmp","     zipnote foo.zip","     edit foo.tmp","     ... then you edit the comments, save, and exit ...","     define/user sys$input foo.tmp","     zipnote -w foo.zip",#else#ifdef RISCOS"     zipnote foo/zip > foo/tmp","     <!Edit> foo/tmp","     ... then you edit the comments, save, and exit ...","     zipnote -w foo/zip < foo/tmp",#else#ifdef VM_CMS"     zipnote foo.zip > foo.tmp","     xedit foo tmp","     ... then you edit the comments, save, and exit ...","     zipnote -w foo.zip < foo.tmp",#else"     zipnote foo.zip > foo.tmp","     ed foo.tmp","     ... then you edit the comments, save, and exit ...","     zipnote -w foo.zip < foo.tmp",#endif /* VM_CMS */#endif /* RISCOS */#endif /* VMS */"","  \"@ name\" can be followed by an \"@=newname\" line to change the name"  };  for (i = 0; i < sizeof(copyright)/sizeof(char *); i++) {    printf(copyright[i], "zipnote");    putchar('\n');  }  for (i = 0; i < sizeof(text)/sizeof(char *); i++)  {    printf(text[i], VERSION, REVDATE);    putchar('\n');  }}/* * XXX put this in version.c */local void version_info()/* Print verbose info about program version and compile time options   to stdout. */{  extent i;             /* counter in text arrays */  /* Options info array */  static ZCONST char *comp_opts[] = {#ifdef DEBUG    "DEBUG",#endif    NULL  };  for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)  {    printf(copyright[i], "zipnote");    putchar('\n');  }  for (i = 0; i < sizeof(versinfolines)/sizeof(char *); i++)  {    printf(versinfolines[i], "ZipNote", VERSION, REVDATE);    putchar('\n');  }  version_local();  puts("ZipNote special compilation options:");  for (i = 0; (int)i < (int)(sizeof(comp_opts)/sizeof(char *) - 1); i++)  {    printf("\t%s\n",comp_opts[i]);  }  if (i == 0)      puts("\t[none]");}local void putclean(s, n)char *s;                /* string to write to stdout */extent n;               /* length of string *//* Write the string s to stdout, filtering out control characters that are   not tab or newline (mainly to remove carriage returns), and prefix MARK's   and backslashes with a backslash.  Also, terminate with a newline if   needed. */{  int c;                /* next character in string */  int e;                /* last character written */  e = '\n';                     /* if empty, write nothing */  while (n--)  {    c = *(uch *)s++;    if (c == MARK || c == '\\')      putchar('\\');    if (c >= ' ' || c == '\t' || c == '\n')      { e=c; putchar(e); }  }  if (e != '\n')    putchar('\n');}local char *zgetline(buf, size)char *buf;extent size;/* Read a line of text from stdin into string buffer 'buf' of size 'size'.   In case of buffer overflow or EOF, a NULL pointer is returned. */{    char *line;    unsigned len;    line = fgets(buf, size, stdin);    if (line != NULL && (len = strlen(line)) > 0) {        if (len == size-1 && line[len-1] != '\n') {            /* buffer is full and record delimiter not seen -> overflow */            line = NULL;        } else {            /* delete trailing record delimiter */            if (line[len-1] == '\n') line[len-1] = '\0';        }    }    return line;}local int catalloc(a, s)char * far *a;          /* pointer to a pointer to a malloc'ed string */char *s;                /* string to concatenate on a *//* Concatentate the string s to the malloc'ed string pointed to by a.   Preprocess s by removing backslash escape characters. */{  char *p;              /* temporary pointer */  char *q;              /* temporary pointer */  for (p = q = s; *q; *p++ = *q++)    if (*q == '\\' && *(q+1))      q++;  *p = 0;  if ((p = malloc(strlen(*a) + strlen(s) + 3)) == NULL)    return ZE_MEM;  strcat(strcat(strcpy(p, *a), **a ? "\r\n" : ""), s);  free((zvoid *)*a);  *a = p;  return ZE_OK;}#ifndef USE_ZIPNOTEMAINint main(argc, argv)#elseint zipnotemain(argc, argv)#endifint argc;               /* number of tokens in command line */char **argv;            /* command line tokens *//* Write the comments in the zipfile to stdout, or read them from stdin. */{  char a[WRBUFSIZ+1];   /* input line buffer */  ulg c;                /* start of central directory */  int k;                /* next argument type */  char *q;              /* steps through option arguments */  int r;                /* arg counter, temporary variable */  ulg s;                /* length of central directory */  int t;                /* attributes of zip file */  int w;                /* true if updating zip file from stdin */  FILE *x, *y;          /* input and output zip files */  struct zlist far *z;  /* steps through zfiles linked list */#ifdef THEOS  setlocale(LC_CTYPE, "I");#endif  /* If no args, show help */  if (argc == 1)  {    help();    EXIT(ZE_OK);  }  /* Direct info messages to stderr; stdout is used for data output. */  mesg = stderr;  init_upper();           /* build case map table */  /* Go through args */  zipfile = tempzip = NULL;  tempzf = NULL;  signal(SIGINT, handler);#ifdef SIGTERM              /* AMIGA has no SIGTERM */  signal(SIGTERM, handler);#endif#ifdef SIGABRT  signal(SIGABRT, handler);#endif#ifdef SIGBREAK  signal(SIGBREAK, handler);#endif#ifdef SIGBUS  signal(SIGBUS, handler);#endif#ifdef SIGILL  signal(SIGILL, handler);#endif#ifdef SIGSEGV  signal(SIGSEGV, handler);#endif  k = w = 0;  for (r = 1; r < argc; r++)    if (*argv[r] == '-') {      if (argv[r][1])        for (q = argv[r]+1; *q; q++)          switch (*q)          {            case 'b':   /* Specify path for temporary file */              if (k)                ziperr(ZE_PARMS, "use -b before zip file name");              else                k = 1;          /* Next non-option is path */              break;            case 'h':   /* Show help */              help();  EXIT(ZE_OK);            case 'l':  case 'L':  /* Show copyright and disclaimer */              license();  EXIT(ZE_OK);            case 'q':   /* Quiet operation, suppress info messages */              noisy = 0;  break;            case 'v':   /* Show version info */              version_info();  EXIT(ZE_OK);            case 'w':              w = 1;  break;            default:              ziperr(ZE_PARMS, "unknown option");          }      else        ziperr(ZE_PARMS, "zip file cannot be stdin");    } else      if (k == 0)      {        if (zipfile == NULL)        {          if ((zipfile = ziptyp(argv[r])) == NULL)            ziperr(ZE_MEM, "was processing arguments");        }        else          ziperr(ZE_PARMS, "can only specify one zip file");      }      else      {        tempath = argv[r];        k = 0;      }  if (zipfile == NULL)    ziperr(ZE_PARMS, "need to specify zip file");  /* Read zip file */  if ((r = readzipfile()) != ZE_OK)    ziperr(r, zipfile);  if (zfiles == NULL)    ziperr(ZE_NAME, zipfile);  /* Put comments to stdout, if not -w */  if (!w)  {    for (z = zfiles; z != NULL; z = z->nxt)    {      printf("%c %s\n", MARK, z->zname);      putclean(z->comment, z->com);      printf("%c%s\n", MARK, MARKE);    }    printf("%c%s\n", MARK, MARKZ);    putclean(zcomment, zcomlen);    EXIT(ZE_OK);  }  /* If updating comments, make sure zip file is writeable */  if ((x = fopen(zipfile, "a")) == NULL)    ziperr(ZE_CREAT, zipfile);  fclose(x);  t = getfileattr(zipfile);  /* Process stdin, replacing comments */  z = zfiles;  while (zgetline(a, WRBUFSIZ+1) != NULL &&         (a[0] != MARK || strcmp(a + 1, MARKZ)))  {                                     /* while input and not file comment */    if (a[0] != MARK || a[1] != ' ')    /* better be "@ name" */      ziperr(ZE_NOTE, "unexpected input");    while (z != NULL && strcmp(a + 2, z->zname))      z = z->nxt;                       /* allow missing entries in order */    if (z == NULL)      ziperr(ZE_NOTE, "unknown entry name");    if (zgetline(a, WRBUFSIZ+1) != NULL && a[0] == MARK && a[1] == '=')    {      if (z->name != z->iname)        free((zvoid *)z->iname);      if ((z->iname = malloc(strlen(a+1))) == NULL)        ziperr(ZE_MEM, "was changing name");#ifdef EBCDIC      strtoasc(z->iname, a+2);#else      strcpy(z->iname, a+2);#endif/* * Don't update z->nam here, we need the old value a little later..... * The update is handled in zipcopy(). */      zgetline(a, WRBUFSIZ+1);    }    if (z->com)                         /* change zip entry comment */      free((zvoid *)z->comment);    z->comment = malloc(1);  *(z->comment) = 0;    while (a != NULL && *a != MARK)    {      if ((r = catalloc(&(z->comment), a)) != ZE_OK)        ziperr(r, "was building new comments");      zgetline(a, WRBUFSIZ+1);    }    z->com = strlen(z->comment);    z = z->nxt;                         /* point to next entry */  }  if (a != NULL)                        /* change zip file comment */  {    zcomment = malloc(1);  *zcomment = 0;    while (zgetline(a, WRBUFSIZ+1) != NULL)      if ((r = catalloc(&zcomment, a)) != ZE_OK)        ziperr(r, "was building new comments");    zcomlen = strlen(zcomment);  }  /* Open output zip file for writing */  if ((tempzf = y = fopen(tempzip = tempname(zipfile), FOPW)) == NULL)    ziperr(ZE_TEMP, tempzip);  /* Open input zip file again, copy preamble if any */  if ((x = fopen(zipfile, FOPR)) == NULL)    ziperr(ZE_NAME, zipfile);  if (zipbeg && (r = fcopy(x, y, zipbeg)) != ZE_OK)    ziperr(r, r == ZE_TEMP ? tempzip : zipfile);  tempzn = zipbeg;  /* Go through local entries, copying them over as is */  fix = 3; /* needed for zipcopy if name changed */  for (z = zfiles; z != NULL; z = z->nxt) {    if ((r = zipcopy(z, x, y)) != ZE_OK)      ziperr(r, "was copying an entry");  }  fclose(x);  /* Write central directory and end of central directory with new comments */  if ((c = ftell(y)) == (ulg)(-1L))    /* get start of central */    ziperr(ZE_TEMP, tempzip);  for (z = zfiles; z != NULL; z = z->nxt)    if ((r = putcentral(z, y)) != ZE_OK)      ziperr(r, tempzip);  if ((s = ftell(y)) == (ulg)-1L)    /* get end of central */    ziperr(ZE_TEMP, tempzip);  s -= c;                       /* compute length of central */  if ((r = putend((int)zcount, s, c, zcomlen, zcomment, y)) != ZE_OK)    ziperr(r, tempzip);  tempzf = NULL;  if (fclose(y))    ziperr(ZE_TEMP, tempzip);  if ((r = replace(zipfile, tempzip)) != ZE_OK)  {    zipwarn("new zip file left as: ", tempzip);    free((zvoid *)tempzip);    tempzip = NULL;    ziperr(r, "was replacing the original zip file");  }  free((zvoid *)tempzip);  tempzip = NULL;  setfileattr(zipfile, t);#ifdef RISCOS  /* Set the filetype of the zipfile to &DDC */  setfiletype(zipfile,0xDDC);#endif  free((zvoid *)zipfile);  zipfile = NULL;  /* Done! */  RETURN(0);}

⌨️ 快捷键说明

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