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

📄 os2zip.c

📁 压缩算法的源代码
💻 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 1897

 *  Ported to OS/2 by Kai Uwe Rommel

 *  December 1989, February 1990

 *  Change for HPFS support, October 1990

 */



/* does also contain EA access code for use in ZIP */





#ifdef __EMX__

#define __32BIT__

#endif



#include "zip.h"



#include <stdlib.h>

#include <time.h>

#include <ctype.h>



#ifdef __WATCOMC__

#include <malloc.h>

unsigned char __near _osmode = OS2_MODE;

#endif



#define INCL_NOPM

#define INCL_DOSNLS

#define INCL_DOSERRORS

#include <os2.h>



#include "os2zip.h"





#define EAID     0x0009





#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 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 UTIL



extern int noisy;



#ifndef S_IFMT

#define S_IFMT 0xF000

#endif



static 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;

#else

static HDIR hdir;

static USHORT count;

static FILEFINDBUF find;

#endif





DIR *opendir(char *name)

{

  struct stat statb;

  DIR *dirp;

  char c;

  char *s;

  struct _dircontents *dp;

  char nbuf[MAXPATHLEN + 1];

  int len;



  strcpy(nbuf, name);

  len = strlen (nbuf);

  s = nbuf + len;



  if ( ((c = nbuf[strlen(nbuf) - 1]) == '\\' || c == '/') &&

       (strlen(nbuf) > 1) )

  {

    nbuf[strlen(nbuf) - 1] = 0;



    if ( nbuf[strlen(nbuf) - 1] == ':' )

      strcat(nbuf, "\\.");

  }

  else

    if ( nbuf[strlen(nbuf) - 1] == ':' )

      strcat(nbuf, ".");



  if (stat(nbuf, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)

    return NULL;



  if ( (dirp = malloc(sizeof(DIR))) == NULL )

    return NULL;



  if ( nbuf[strlen(nbuf) - 1] == '.' )

    strcpy(nbuf + strlen(nbuf) - 1, "*.*");

  else

    if ( ((c = nbuf[strlen(nbuf) - 1]) == '\\' || c == '/') &&

         (strlen(nbuf) == 1) )

      strcat(nbuf, "*.*");

    else

      strcat(nbuf, "\\*.*");



  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 direct *readdir(DIR * dirp)

{

  static struct direct 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_CREATE;

    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], bName[3];

#ifdef __32BIT__

  ULONG nDrive, cbData;

  PFSQBUFFER2 pData = (PFSQBUFFER2) bData;

#else

  USHORT nDrive, cbData;

  PFSQBUFFER pData = (PFSQBUFFER) bData;

#endif



  if ( _osmode == DOS_MODE )

    return TRUE;

  else

  {

    /* 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 beeing 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(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

}



long GetFileTime(char *name)

{

#ifdef __32BIT__

  FILESTATUS3 fs;

#else

  FILESTATUS fs;

#endif

  USHORT nDate, nTime;



  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, long stamp)

{

  FILESTATUS fs;

  USHORT fd, ft;

  USHORT nLength;

  char szName[CCHMAXPATH];



  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);

}





/* 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

{

⌨️ 快捷键说明

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