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

📄 os2zip.c

📁 给出了 zip 压缩算法的完整实现过程。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * @(#)dir.c 1.4 87/11/06 Public Domain. * *  A public domain implementation of BSD directory routines for *  MS-DOS.  Written by Michael Rendell ({uunet,utai}michael@garfield), *  August 1987 * *  Ported to OS/2 by Kai Uwe Rommel *  Addition of other OS/2 file system specific code *  Placed into the public domain *//* does also contain EA access code for use in ZIP */#ifdef OS2#if defined(__EMX__) && !defined(__32BIT__)#  define __32BIT__#endif#include "zip.h"#include <stdlib.h>#include <time.h>#include <ctype.h>#ifndef __BORLANDC__#include <malloc.h>#endif#define INCL_NOPM#define INCL_DOSNLS#define INCL_DOSERRORS#include <os2.h>#include "os2zip.h"#include "os2acl.h"#ifndef max#define max(a, b) ((a) < (b) ? (b) : (a))#endif#ifdef __32BIT__#define DosFindFirst(p1, p2, p3, p4, p5, p6) \        DosFindFirst(p1, p2, p3, p4, p5, p6, 1)#else#define DosQueryCurrentDisk DosQCurDisk#define DosQueryFSAttach(p1, p2, p3, p4, p5) \        DosQFSAttach(p1, p2, p3, p4, p5, 0)#define DosQueryFSInfo(d, l, b, s) \        DosQFSInfo(d, l, b, s)#define DosQueryPathInfo(p1, p2, p3, p4) \        DosQPathInfo(p1, p2, p3, p4, 0)#define DosSetPathInfo(p1, p2, p3, p4, p5) \        DosSetPathInfo(p1, p2, p3, p4, p5, 0)#define DosEnumAttribute(p1, p2, p3, p4, p5, p6, p7) \        DosEnumAttribute(p1, p2, p3, p4, p5, p6, p7, 0)#define DosFindFirst(p1, p2, p3, p4, p5, p6) \        DosFindFirst(p1, p2, p3, p4, p5, p6, 0)#define DosMapCase DosCaseMap#endif#ifndef UTILextern int noisy;#ifndef S_IFMT#define S_IFMT 0xF000#endifstatic int attributes = _A_DIR | _A_HIDDEN | _A_SYSTEM;static char *getdirent(char *);static void free_dircontents(struct _dircontents *);#ifdef __32BIT__static HDIR hdir;static ULONG count;static FILEFINDBUF3 find;#elsestatic HDIR hdir;static USHORT count;static FILEFINDBUF find;#endifDIR *opendir(const char *name){  struct stat statb;  DIR *dirp;  char c;  char *s;  struct _dircontents *dp;  char nbuf[MAXPATHLEN + 1];  int len;  attributes = hidden_files ? (_A_DIR | _A_HIDDEN | _A_SYSTEM) : _A_DIR;  strcpy(nbuf, name);  if ((len = strlen(nbuf)) == 0)    return NULL;  if (((c = nbuf[len - 1]) == '\\' || c == '/') && (len > 1))  {    nbuf[len - 1] = 0;    --len;    if (nbuf[len - 1] == ':')    {      strcpy(nbuf+len, "\\.");      len += 2;    }  }  else    if (nbuf[len - 1] == ':')    {      strcpy(nbuf+len, ".");      ++len;    }#ifndef __BORLANDC__  /* when will we ever see a Borland compiler that can properly stat !!! */  if (stat(nbuf, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)    return NULL;#endif  if ((dirp = malloc(sizeof(DIR))) == NULL)    return NULL;  if (nbuf[len - 1] == '.' && (len == 1 || nbuf[len - 2] != '.'))    strcpy(nbuf+len-1, "*.*");  else    if (((c = nbuf[len - 1]) == '\\' || c == '/') && (len == 1))      strcpy(nbuf+len, "*");    else      strcpy(nbuf+len, "\\*");  /* len is no longer correct (but no longer needed) */  dirp -> dd_loc = 0;  dirp -> dd_contents = dirp -> dd_cp = NULL;  if ((s = getdirent(nbuf)) == NULL)    return dirp;  do  {    if (((dp = malloc(sizeof(struct _dircontents))) == NULL) ||        ((dp -> _d_entry = malloc(strlen(s) + 1)) == NULL)      )    {      if (dp)        free(dp);      free_dircontents(dirp -> dd_contents);      return NULL;    }    if (dirp -> dd_contents)    {      dirp -> dd_cp -> _d_next = dp;      dirp -> dd_cp = dirp -> dd_cp -> _d_next;    }    else      dirp -> dd_contents = dirp -> dd_cp = dp;    strcpy(dp -> _d_entry, s);    dp -> _d_next = NULL;    dp -> _d_size = find.cbFile;    dp -> _d_mode = find.attrFile;    dp -> _d_time = *(unsigned *) &(find.ftimeLastWrite);    dp -> _d_date = *(unsigned *) &(find.fdateLastWrite);  }  while ((s = getdirent(NULL)) != NULL);  dirp -> dd_cp = dirp -> dd_contents;  return dirp;}void closedir(DIR * dirp){  free_dircontents(dirp -> dd_contents);  free(dirp);}struct dirent *readdir(DIR * dirp){  static struct dirent dp;  if (dirp -> dd_cp == NULL)    return NULL;  dp.d_namlen = dp.d_reclen =    strlen(strcpy(dp.d_name, dirp -> dd_cp -> _d_entry));  dp.d_ino = 0;  dp.d_size = dirp -> dd_cp -> _d_size;  dp.d_mode = dirp -> dd_cp -> _d_mode;  dp.d_time = dirp -> dd_cp -> _d_time;  dp.d_date = dirp -> dd_cp -> _d_date;  dirp -> dd_cp = dirp -> dd_cp -> _d_next;  dirp -> dd_loc++;  return &dp;}void seekdir(DIR * dirp, long off){  long i = off;  struct _dircontents *dp;  if (off >= 0)  {    for (dp = dirp -> dd_contents; --i >= 0 && dp; dp = dp -> _d_next);    dirp -> dd_loc = off - (i + 1);    dirp -> dd_cp = dp;  }}long telldir(DIR * dirp){  return dirp -> dd_loc;}static void free_dircontents(struct _dircontents * dp){  struct _dircontents *odp;  while (dp)  {    if (dp -> _d_entry)      free(dp -> _d_entry);    dp = (odp = dp) -> _d_next;    free(odp);  }}static char *getdirent(char *dir){  int done;  static int lower;  if (dir != NULL)  {                                    /* get first entry */    hdir = HDIR_SYSTEM;    count = 1;    done = DosFindFirst(dir, &hdir, attributes, &find, sizeof(find), &count);    lower = IsFileSystemFAT(dir);  }  else                                 /* get next entry */    done = DosFindNext(hdir, &find, sizeof(find), &count);  if (done == 0)  {    if (lower)      StringLower(find.achName);    return find.achName;  }  else  {    DosFindClose(hdir);    return NULL;  }}/* FAT / HPFS detection */int IsFileSystemFAT(char *dir){  static USHORT nLastDrive = -1, nResult;  ULONG lMap;  BYTE bData[64];  char bName[3];#ifdef __32BIT__  ULONG nDrive, cbData;  PFSQBUFFER2 pData = (PFSQBUFFER2) bData;#else  USHORT nDrive, cbData;  PFSQBUFFER pData = (PFSQBUFFER) bData;#endif  /* We separate FAT and HPFS+other file systems here.     at the moment I consider other systems to be similar to HPFS,     i.e. support long file names and being case sensitive */  if (isalpha(dir[0]) && (dir[1] == ':'))    nDrive = to_up(dir[0]) - '@';  else    DosQueryCurrentDisk(&nDrive, &lMap);  if (nDrive == nLastDrive)    return nResult;  bName[0] = (char) (nDrive + '@');  bName[1] = ':';  bName[2] = 0;  nLastDrive = nDrive;  cbData = sizeof(bData);  if (!DosQueryFSAttach(bName, 0, FSAIL_QUERYNAME, (PVOID) pData, &cbData))    nResult = !strcmp((char *) pData -> szFSDName + pData -> cbName, "FAT");  else    nResult = FALSE;  /* End of this ugly code */  return nResult;}/* access mode bits and time stamp */int GetFileMode(char *name){#ifdef __32BIT__  FILESTATUS3 fs;  return DosQueryPathInfo(name, 1, &fs, sizeof(fs)) ? -1 : fs.attrFile;#else  USHORT mode;  return DosQFileMode(name, &mode, 0L) ? -1 : mode;#endif}ulg GetFileTime(char *name){#ifdef __32BIT__  FILESTATUS3 fs;#else  FILESTATUS fs;#endif  USHORT nDate, nTime;  DATETIME dtCurrent;  if (strcmp(name, "-") == 0)  {    DosGetDateTime(&dtCurrent);    fs.fdateLastWrite.day     = dtCurrent.day;    fs.fdateLastWrite.month   = dtCurrent.month;    fs.fdateLastWrite.year    = dtCurrent.year - 1980;    fs.ftimeLastWrite.hours   = dtCurrent.hours;    fs.ftimeLastWrite.minutes = dtCurrent.minutes;    fs.ftimeLastWrite.twosecs = dtCurrent.seconds / 2;  }  else    if (DosQueryPathInfo(name, 1, (PBYTE) &fs, sizeof(fs)))      return -1;  nDate = * (USHORT *) &fs.fdateLastWrite;  nTime = * (USHORT *) &fs.ftimeLastWrite;  return ((ULONG) nDate) << 16 | nTime;}void SetFileTime(char *path, ulg stamp){  FILESTATUS fs;  USHORT fd, ft;  if (DosQueryPathInfo(path, FIL_STANDARD, (PBYTE) &fs, sizeof(fs)))    return;  fd = (USHORT) (stamp >> 16);  ft = (USHORT) stamp;  fs.fdateLastWrite = fs.fdateCreation = * (FDATE *) &fd;  fs.ftimeLastWrite = fs.ftimeCreation = * (FTIME *) &ft;  DosSetPathInfo(path, FIL_STANDARD, (PBYTE) &fs, sizeof(fs), 0);}/* read volume label */char *getVolumeLabel(int drive, unsigned long *vtime, unsigned long *vmode,                     time_t *utim){  static FSINFO fi;  if (DosQueryFSInfo(drive ? drive - 'A' + 1 : 0,                     FSIL_VOLSER, (PBYTE) &fi, sizeof(fi)))    return NULL;  time(utim);  *vtime = unix2dostime(utim);  *vmode = _A_VOLID | _A_ARCHIVE;  return (fi.vol.cch > 0) ? fi.vol.szVolLabel : NULL;}/* FAT / HPFS name conversion stuff */int IsFileNameValid(char *name){  HFILE hf;#ifdef __32BIT__  ULONG uAction;#else  USHORT uAction;#endif  switch(DosOpen(name, &hf, &uAction, 0, 0, FILE_OPEN,                 OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, 0))  {  case ERROR_INVALID_NAME:  case ERROR_FILENAME_EXCED_RANGE:    return FALSE;  case NO_ERROR:    DosClose(hf);  default:    return TRUE;  }}void ChangeNameForFAT(char *name){  char *src, *dst, *next, *ptr, *dot, *start;  static char invalid[] = ":;,=+\"[]<>| \t";  if (isalpha(name[0]) && (name[1] == ':'))    start = name + 2;  else    start = name;  src = dst = start;  if ((*src == '/') || (*src == '\\'))    src++, dst++;  while (*src)  {    for (next = src; *next && (*next != '/') && (*next != '\\'); next++);    for (ptr = src, dot = NULL; ptr < next; ptr++)      if (*ptr == '.')      {        dot = ptr; /* remember last dot */        *ptr = '_';      }    if (dot == NULL)      for (ptr = src; ptr < next; ptr++)        if (*ptr == '_')          dot = ptr; /* remember last _ as if it were a dot */    if (dot && (dot > src) &&        ((next - dot <= 4) ||         ((next - src > 8) && (dot - src > 3))))    {      if (dot)        *dot = '.';      for (ptr = src; (ptr < dot) && ((ptr - src) < 8); ptr++)        *dst++ = *ptr;      for (ptr = dot; (ptr < next) && ((ptr - dot) < 4); ptr++)        *dst++ = *ptr;    }    else    {      if (dot && (next - src == 1))        *dot = '.';           /* special case: "." as a path component */      for (ptr = src; (ptr < next) && ((ptr - src) < 8); ptr++)        *dst++ = *ptr;    }    *dst++ = *next; /* either '/' or 0 */    if (*next)    {      src = next + 1;      if (*src == 0) /* handle trailing '/' on dirs ! */        *dst = 0;    }    else      break;  }  for (src = start; *src != 0; ++src)    if ((strchr(invalid, *src) != NULL) || (*src == ' '))      *src = '_';}/* .LONGNAME EA code */typedef struct{  ULONG cbList;               /* length of value + 22 */#ifdef __32BIT__  ULONG oNext;#endif  BYTE fEA;                   /* 0 */  BYTE cbName;                /* length of ".LONGNAME" = 9 */  USHORT cbValue;             /* length of value + 4 */  BYTE szName[10];            /* ".LONGNAME" */  USHORT eaType;              /* 0xFFFD for length-preceded ASCII */  USHORT eaSize;              /* length of value */  BYTE szValue[CCHMAXPATH];}FEALST;typedef struct{  ULONG cbList;#ifdef __32BIT__  ULONG oNext;#endif  BYTE cbName;  BYTE szName[10];            /* ".LONGNAME" */}GEALST;char *GetLongNameEA(const char *name){  EAOP eaop;  GEALST gealst;  static FEALST fealst;  char *ptr;  eaop.fpGEAList = (PGEALIST) &gealst;  eaop.fpFEAList = (PFEALIST) &fealst;  eaop.oError = 0;  strcpy((char *) gealst.szName, ".LONGNAME");  gealst.cbName  = (BYTE) strlen((char *) gealst.szName);#ifdef __32BIT__  gealst.oNext   = 0;#endif  gealst.cbList  = sizeof(gealst);  fealst.cbList  = sizeof(fealst);  if (DosQueryPathInfo(name, FIL_QUERYEASFROMLIST,                       (PBYTE) &eaop, sizeof(eaop)))    return NULL;  if (fealst.cbValue > 4 && fealst.eaType == 0xFFFD)  {    fealst.szValue[fealst.eaSize] = 0;    for (ptr = fealst.szValue; *ptr; ptr++)      if (*ptr == '/' || *ptr == '\\')        *ptr = '!';    return (char *) fealst.szValue;  }  return NULL;}char *GetLongPathEA(const char *name){  static char nbuf[CCHMAXPATH + 1];  char tempbuf[CCHMAXPATH + 1];  char *comp, *next, *ea, sep;  BOOL bFound = FALSE;  nbuf[0] = 0;  strncpy(tempbuf, name, CCHMAXPATH);  tempbuf[CCHMAXPATH] = '\0';  next = tempbuf;  while (*next)  {    comp = next;    while (*next != '\\' && *next != '/' && *next != 0)      next++;    sep = *next;    *next = 0;    ea = GetLongNameEA(tempbuf);    strcat(nbuf, ea ? ea : comp);    bFound = bFound || (ea != NULL);    if (sep)    {      strcat(nbuf, "\\");      *next++ = sep;    }  }  return (nbuf[0] != 0) && bFound ? nbuf : NULL;}/* general EA code */typedef struct{  USHORT nID;  USHORT nSize;  ULONG lSize;}EFHEADER, *PEFHEADER;#ifdef __32BIT__/* Perhaps due to bugs in the current OS/2 2.0 kernel, the success or   failure of the DosEnumAttribute() and DosQueryPathInfo() system calls   depends on the area where the return buffers are allocated. This   differs for the various compilers, for some alloca() works, for some

⌨️ 快捷键说明

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