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

📄 theos.c

📁 给出了 zip 压缩算法的完整实现过程。
💻 C
字号:
/*  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.  See the accompanying file LICENSE, version 2004-May-22 or later  (the contents of which are also included in zip.h) for terms of use.  If, for some reason, both of these files are missing, the Info-ZIP license  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html*//*---------------------------------------------------------------------------  theos.c (zip)  Contribution by Jean-Michel Dubois. 20-Jun-1995, 20-Dec-98  THEOS specific extra informations  ---------------------------------------------------------------------------*/#include <stdio.h>#ifndef UTIL#include "zip.h"#include <stdlib.h>#include <ctype.h>#include <time.h>#include <sc.h>#include <direct.h>#include <sys/utime.h>#define opendir(a) _opendir(a)extern struct dirent* _opendir(char* fname);#define PAD 0#define RET_ERROR 1#define RET_SUCCESS 0#define RET_EOF 0extern char *label;local ulg label_time = 0;local ulg label_mode = 0;local time_t label_utim = 0;/* match from Phase One Systems */int match(char *s, char *p)    /*S Returns non-zero if string matches                                   the literal mask */{  int matched, k;  if (!(*p))    return 1;  for(;;) {    if ( (!(*s)) && (!(*p)) )      return(1);    else if ( !(*p) )      return(0);    else if (*p == '*') {      if (!*(p+1))        return(1);      k=0;      do {        matched = match(s+k,p+1);        k++;      } while ( (!matched) && *(s+k));      return(matched);    } else if (*p == '@') {      if (!((*s >= 'a' && *s <= 'z')          ||(*s >= 'A' && *s <= 'Z')))        return(0);    } else if (*p == '#') {      if (*s < '0' || *s > '9')        return(0);    } else if (*p != '?') {      if (tolower(*s) != tolower(*p))        return(0);    }    s++; p++;  }}local char *readd(d)DIR *d; /* directory stream to read from *//* Return a pointer to the next name in the directory stream d, or NULL if   no more entries or an error occurs. */{  struct dirent *e;  e = readdir(d);  return e == NULL ? (char *) NULL : e->d_name;}/* check if file is a member of a library */int ismember(char* path){    char* p;    if ((p = strrchr(path, '/')) == NULL)        p = path;    return ((p = strchr(p, '.')) && (p = strchr(p + 1, '.')));}/* extract library name from a file name */char* libname(char* path){    char* p;    static char lib[FILENAME_MAX];    char drive[3];    strcpy(lib, path);    if (p = strrchr(lib, ':')) {        strncpy(drive, p, 2);        drive[2] = '\0';        *p = '\0' ;    } else        drive[0] = '\0';    if ((p = strrchr(lib, '/')) == NULL)        p = lib;    p = strchr(p, '.');    p = strchr(p + 1, '.');    *p = 0;    strcat(lib, drive);    return lib;}int procname(n, caseflag)char *n;                /* name to process */int caseflag;           /* true to force case-sensitive match *//* Process a name or sh expression to operate on (or exclude).  Return   an error code in the ZE_ class. */{  char *a;              /* path and name for recursion */  DIR *d;               /* directory stream from opendir() */  char *e;              /* pointer to name from readd() */  int m;                /* matched flag */  char *p;              /* path for recursion */  struct stat s;        /* result of stat() */  struct zlist *z;      /* steps through zfiles list */  struct flist *f;      /* steps through files list */  char* path;           /* full name */  char drive[3];        /* drive name */  int recursion;        /* save recurse flag */  if (strcmp(n, "-") == 0)   /* if compressing stdin */    return newname(n, 0, caseflag);  else if (LSSTAT(n, &s)) {    /* Not a file or directory--search for shell expression in zip file */    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */    m = 1;    for (z = zfiles; z != NULL; z = z->nxt) {      if (match(z->iname, p))      {        z->mark = pcount ? filter(z->zname, caseflag) : 1;        if (verbose)            fprintf(mesg, "zip diagnostic: %scluding %s\n",               z->mark ? "in" : "ex", z->name);        m = 0;      }    }    free((zvoid *)p);    return m ? ZE_MISS : ZE_OK;  }  /* Live name--use if file, recurse if directory or library */  if (S_ISREG(s.st_mode)) {    if ((path = malloc(strlen(n) + 2)) == NULL)      return ZE_MEM;    strcpy(path, n);    /* if member name, include library name before any member name */    if (ismember(path)) {      strcpy(path, libname(path));      /* mask recursion flag to avoid endless loop recursion       * if -r is used with member names       */      recursion = recurse;      recurse = FALSE;      if ((m = procname(path, caseflag)) != ZE_OK)   /* recurse on name */      {        if (m == ZE_MISS)          zipwarn("name not matched: ", path);        else          ziperr(m, a);      }      /* restore recursion flag */      recurse = recursion;    }    strcpy(path, n);    if ((p = strchr(path, ':')) != NULL) {      p[2] = '\0';      strcpy(drive, p);    } else      drive[0] = '\0';    /* remove trailing dot in flat file name */    p = strend(path) - 1;    if (*p == '.')      *p = '\0';    strcat(path, drive);    /* add or remove name of file */    if ((m = newname(path, 0, caseflag)) != ZE_OK) {      free(path);      return m;    }    free(path);  } else if (S_ISLIB(s.st_mode)) {    if ((path = malloc(strlen(n) + 2)) == NULL)      return ZE_MEM;    strcpy(path, n);    if ((p = strchr(path, ':')) != NULL) {      p[2] = '\0';      strcpy(drive, p);    } else      drive[0] = '\0';    /* add a trailing dot in flat file name... */    p = strend(path) - 1;    if (*p != '/')      strcat(path, "/");    p = strend(path);    /* ... then add drive name */    strcpy(p, drive);    /* don't include the library name twice... or more */    for (f = found; f != NULL; f = f->nxt) {      if (! stricmp(path, f->name)) {        free(path);        return ZE_OK;      }    }    /* add or remove name of library */    if ((m = newname(path, 0, caseflag)) != ZE_OK) {      free(path);      return m;    }    /* recurse into library if required */    strcpy(p - 1, ".*");    strcat(p, drive);    if (recurse && diropen(path) == 0)    {      while ((e = dirread()) != NULL) {        if (strcmp(e, ".") && strcmp(e, ".."))        {          if (*drive == '\0')            *strchr(e, ':') = '\0';          if ((a = malloc(strlen(e) + 1)) == NULL)          {            dirclose();            free((zvoid *)p);            return ZE_MEM;          }          strcpy(a, e);          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */          {            if (m == ZE_MISS)              zipwarn("name not matched: ", a);            else              ziperr(m, a);          }          free((zvoid *)a);        }      }      dirclose();    }    free(path);  } else {    /* Add trailing / to the directory name */    if ((p = malloc(strlen(n)+2)) == NULL)      return ZE_MEM;    if (strcmp(n, ".") == 0) {      *p = '\0';  /* avoid "./" prefix and do not create zip entry */    } else {      strcpy(p, n);      a = p + strlen(p);      if (a[-1] != '/')        strcpy(a, "/");      if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {        free((zvoid *)p);        return m;      }    }    /* recurse into directory */    if (recurse && (d = opendir(n)) != NULL)    {      while ((e = readd(d)) != NULL) {        if (strcmp(e, ".") && strcmp(e, ".."))        {          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)          {            closedir(d);            free((zvoid *)p);            return ZE_MEM;          }          strcat(strcpy(a, p), e);          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */          {            if (m == ZE_MISS)              zipwarn("name not matched: ", a);            else              ziperr(m, a);          }          free((zvoid *)a);        }      }      closedir(d);    }    free((zvoid *)p);  }  return ZE_OK;}char *ex2in(x, isdir, pdosflag)char *x;                /* external file name */int isdir;              /* input: x is a directory */int *pdosflag;          /* output: force MSDOS file attributes? *//* Convert the external file name to a zip file name, returning the malloc'ed   string or NULL if not enough memory. */{  char *n;              /* internal file name (malloc'ed) */  char *t;              /* shortened name */  char *p;  int dosflag;  dosflag = dosify;  /* default for non-DOS and non-OS/2 */  /* Find starting point in name before doing malloc */  for (t = x; *t == '/'; t++)    ;  /* Make changes, if any, to the copied name (leave original intact) */  if (!pathput)    t = last(t, '/');  /* Malloc space for internal name and copy it */  if ((n = malloc(strlen(t) + 1)) == NULL)    return NULL;  strcpy(n, t);  if (p = strchr(n, ':'))    *p = '\0';  for (p = n; *p = tolower(*p); p++);  if (isdir == 42) return n;      /* avoid warning on unused variable */  if (dosify)    msname(n);  /* Returned malloc'ed name */  if (pdosflag)    *pdosflag = dosflag;  return n;}char *in2ex(n)char *n;                /* internal file name *//* Convert the zip file name to an external file name, returning the malloc'ed   string or NULL if not enough memory. */{  char *x;              /* external file name */  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)    return NULL;  strcpy(x, n);  return x;}/* * XXX use ztimbuf in both POSIX and non POSIX cases ? */void stamp(f, d)char *f;                /* name of file to change */ulg d;                  /* dos-style time to change it to *//* Set last updated and accessed time of file f to the DOS time d. */{  struct utimbuf u;     /* argument for utime()  const ?? */  /* Convert DOS time to time_t format in u */  u.actime = u.modtime = dos2unixtime(d);  utime(f, &u);}ulg filetime(f, a, n, t)char *f;                /* name of file to get info on */ulg *a;                 /* return value: file attributes */long *n;                /* return value: file size */iztimes *t;             /* return value: access, modific. and creation times *//* If file *f does not exist, return 0.  Else, return the file's last   modified date and time as an MSDOS date and time.  The date and   time is returned in a long with the date most significant to allow   unsigned integer comparison of absolute times.  Also, if a is not   a NULL pointer, store the file attributes there, with the high two   bytes being the Unix attributes, and the low byte being a mapping   of that to DOS attributes. Bits 8 to 15 contains native THEOS protection   code. If n is not NULL, store the file size there.  If t is not NULL,   the file's access, modification and creation times are stored there as   UNIX time_t values. If f is "-", use standard input as the file. If f is   a device, return a file size of -1 */{  struct stat s;        /* results of stat() */  char *name;  unsigned int len = strlen(f);  if (f == label) {    if (a != NULL)      *a = label_mode;    if (n != NULL)      *n = -2L; /* convention for a label name */    if (t != NULL)      t->atime = t->mtime = t->ctime = label_utim;    return label_time;  }  if ((name = malloc(len + 1)) == NULL) {    ZIPERR(ZE_MEM, "filetime");  }  strcpy(name, f);  if (name[len - 1] == '/' || name[len - 1] == '.')    name[len - 1] = '\0';  /* not all systems allow stat'ing a file with / appended */  if (strcmp(f, "-") == 0) {    if (fstat(fileno(stdin), &s) != 0) {      free(name);      error("fstat(stdin)");    }  } else if (LSSTAT(name, &s) != 0) {    /* Accept about any file kind including directories     * (stored with trailing / with -r option)     */    free(name);    return 0;  }  if (a != NULL) {    *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);    if ((s.st_mode & S_IFMT) == S_IFDIR     || (s.st_mode & S_IFMT) == S_IFLIB) {      *a |= MSDOS_DIR_ATTR;    }    /* Map Theos' hidden attribute to DOS's hidden attribute */    if (!(st.st_protect & 0x80))      *a |= MSDOS_HIDDEN_ATTR;    *a |= ((ulg) s.st_protect) << 8;  }  if (n != NULL)    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;  if (t != NULL) {    t->atime = s.st_atime;    t->mtime = s.st_mtime;    t->ctime = t->mtime;   /* best guess, (s.st_ctime: last status change!!) */  }  free(name);  return unix2dostime(&s.st_mtime);}/* *      Get file THEOS attributes and store them into extent fields. *      On error leave z intact. *//**   Extra record format*   ===================*   signature       (2 bytes)   = 'T','h'*   size            (2 bytes)*   flags           (1 byte)*   filesize        (4 bytes)*   keylen          (2 bytes)*   reclen          (2 bytes)*   filegrow        (1 byte)*   reserved        (4 bytes)*/#define EB_L_THSIZE     4#define EB_L_TH_SIZE    14int set_extra_field(z, z_utim)  struct zlist *z;  iztimes *z_utim;  /* store full data in local header but just modification time stamp info     in central header */{  char *extra = NULL;  char *p;  char c;  struct stat st;  int status;  if (status = stat(z->name, &st)) {    p = &z->name[strlen(z->name) - 1];    if (*p == '/' || *p == '.') {      c = *p;      *p = '\0';      status = stat(z->name, &st);      *p = c;    }#ifdef DEBUG    fprintf(stderr, "set_extra_field: stat for file %s:\n status = %d\n",        z->name, status);#endif    if (status)      return RET_ERROR;  }  if ((extra = malloc(EB_L_TH_SIZE)) == NULL ) {    fprintf(stderr, "set_extra_field: Insufficient memory.\n" );    return RET_ERROR;  }  extra[0] = 'T';  extra[1] = 'h';  extra[2] = EB_L_TH_SIZE;  extra[3] = EB_L_TH_SIZE >> 8;  extra[4] = 0;  extra[5] = st.st_size;  extra[6] = st.st_size >> 8;  extra[7] = st.st_size >> 16;  extra[8] = st.st_size >> 24;  extra[9] = st.st_org;  extra[10] = st.st_rlen;  extra[11] = st.st_rlen >> 8;  extra[12] = st.st_klen;  extra[13] = st.st_klen >> 8;  extra[14] = st.st_grow;  extra[15] = st.st_protect;  extra[16] = 0;  extra[17] = 0;  z->ext = z->cext = EB_L_TH_SIZE + EB_HEADSIZE;  z->extra = z->cextra = extra;  return RET_SUCCESS;}#endif/******************************//*  Function version_local()  *//******************************/void version_local(){  printf("Compiled with THEOS C 5.28 for THEOS 4.x on %s %s.\n\n",    __DATE__, __TIME__);}

⌨️ 快捷键说明

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