ftp.nice.ch/pub/next/unix/archiver/unzip.5.01.N.s.tar.gz#/unzip/OS2/os2unzip.c

This is os2unzip.c in view mode; [Download] [Up]

/* Unix/HPFS filename translation for FAT file systems */
/*  (with special unzip modifications:  sflag) */

/* also includes lots of EA code for OS/2 */

/* Author: Kai Uwe Rommel */

#include "unzip.h"

#define INCL_NOPM
#define INCL_DOSNLS
#define INCL_DOSERRORS
#define ULONG _ULONG
#include <os2.h>
#undef ULONG

#ifdef __WATCOMC__
unsigned char __near _osmode = OS2_MODE;
#endif


#define EAID     0x0009


extern int tflag, quietflg;


typedef struct
{
  USHORT nID;
  USHORT nSize;
  ULONG lSize;
}
EAHEADER, *PEAHEADER;


#ifndef __32BIT__

typedef struct
{
  ULONG oNextEntryOffset;
  BYTE fEA;
  BYTE cbName;
  USHORT cbValue;
  CHAR szName[1];
}
FEA2, *PFEA2;

typedef struct
{
  ULONG cbList;
  FEA2 list[1];
}
FEA2LIST, *PFEA2LIST;

#endif


#ifndef __32BIT__
#define DosSetPathInfo(p1, p2, p3, p4, p5) \
        DosSetPathInfo(p1, p2, p3, p4, p5, 0)
#define DosQueryPathInfo(p1, p2, p3, p4) \
	DosQPathInfo(p1, p2, p3, p4, 0)
#define DosMapCase DosCaseMap
#define DosQueryCtryInfo DosGetCtryInfo
#endif


#ifndef ZIPINFO


extern int sflag;  /* user wants to allow spaces (e.g., "EA DATA. SF") */

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 == ' ') && !sflag) )  /* allow spaces if user wants */
        *src = '_';
}


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


int GetCountryInfo(void)
{
    COUNTRYINFO ctryi;
    COUNTRYCODE ctryc;
#ifdef __32BIT__
    ULONG cbInfo;
#else
    USHORT cbInfo;
#endif

  ctryc.country = ctryc.codepage = 0;

  if ( DosQueryCtryInfo(sizeof(ctryi), &ctryc, &ctryi, &cbInfo) != NO_ERROR )
    return 0;

  return ctryi.fsDateFmt;
}


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 SetPathInfo(char *path, UWORD moddate, UWORD modtime, int flags)
{
  union {
    FDATE fd;               /* system file date record */
    UWORD zdate;            /* date word */
  } ud;
  union {
    FTIME ft;               /* system file time record */
    UWORD ztime;            /* time word */
  } ut;
  FILESTATUS fs;
  USHORT nLength;
  char szName[CCHMAXPATH];

  strcpy(szName, path);
  nLength = strlen(szName);
  if (szName[nLength - 1] == '/')
    szName[nLength - 1] = 0;

  if ( DosQueryPathInfo(szName, FIL_STANDARD, (PBYTE) &fs, sizeof(fs)) )
    return;

  ud.zdate = moddate;
  ut.ztime = modtime;
  fs.fdateLastWrite = fs.fdateCreation = ud.fd;
  fs.ftimeLastWrite = fs.ftimeCreation = ut.ft;

  if ( flags != -1 )
    fs.attrFile = flags; /* hidden, system, archive, read-only */

  DosSetPathInfo(szName, FIL_STANDARD, (PBYTE) &fs, sizeof(fs), 0);
}


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;


int SetLongNameEA(char *name, char *longname)
{
  EAOP eaop;
  FEALST fealst;

  if ( _osmode == DOS_MODE )
    return 0;

  eaop.fpFEAList = (PFEALIST) &fealst;
  eaop.fpGEAList = NULL;
  eaop.oError = 0;

  strcpy(fealst.szName, ".LONGNAME");
  strcpy(fealst.szValue, longname);

  fealst.cbList  = sizeof(fealst) - CCHMAXPATH + strlen(fealst.szValue);
  fealst.cbName  = (BYTE) strlen(fealst.szName);
  fealst.cbValue = sizeof(USHORT) * 2 + strlen(fealst.szValue);

#ifdef __32BIT__
  fealst.oNext   = 0;
#endif
  fealst.fEA     = 0;
  fealst.eaType  = 0xFFFD;
  fealst.eaSize  = strlen(fealst.szValue);

  return DosSetPathInfo(name, FIL_QUERYEASIZE,
                        (PBYTE) &eaop, sizeof(eaop), 0);
}


int IsEA(void *extra_field)
{
  EAHEADER *pEAblock = (PEAHEADER) extra_field;
  return extra_field != NULL && pEAblock -> nID == EAID;
}


void SetEAs(char *path, void *eablock)
{
  EAHEADER *pEAblock = (PEAHEADER) eablock;
#ifdef __32BIT__
  EAOP2 eaop;
  PFEA2LIST pFEA2list;
#else
  EAOP eaop;
  PFEALIST pFEAlist;
  PFEA pFEA;
  PFEA2LIST pFEA2list;
  PFEA2 pFEA2;
  ULONG nLength2;
#endif
  USHORT nLength;
  char szName[CCHMAXPATH];

  if ( !IsEA(eablock) )
    return;

  if ( _osmode == DOS_MODE )
    return;

  strcpy(szName, path);
  nLength = strlen(szName);
  if (szName[nLength - 1] == '/')
    szName[nLength - 1] = 0;

  if ( (pFEA2list = (PFEA2LIST) malloc((size_t) pEAblock -> lSize)) == NULL )
    return;

  if ( memextract((char *) pFEA2list, pEAblock -> lSize,
	          (char *) (pEAblock + 1), 
		  pEAblock -> nSize - sizeof(pEAblock -> lSize)) )
  {
    free(pFEA2list);
    return;
  }

#ifdef __32BIT__
  eaop.fpGEA2List = NULL;
  eaop.fpFEA2List = pFEA2list;
#else
  pFEAlist  = (PVOID) pFEA2list;
  pFEA2 = pFEA2list -> list;
  pFEA  = pFEAlist  -> list;

  do
  {
    nLength2 = pFEA2 -> oNextEntryOffset;
    nLength = sizeof(FEA) + pFEA2 -> cbName + 1 + pFEA2 -> cbValue;

    memcpy(pFEA, (PCH) pFEA2 + sizeof(pFEA2 -> oNextEntryOffset), nLength);

    pFEA2 = (PFEA2) ((PCH) pFEA2 + nLength2);
    pFEA = (PFEA) ((PCH) pFEA + nLength);
  }
  while ( nLength2 != 0 );

  pFEAlist -> cbList = (PCH) pFEA - (PCH) pFEAlist;

  eaop.fpGEAList = NULL;
  eaop.fpFEAList = pFEAlist;
#endif

  eaop.oError = 0;
  DosSetPathInfo(szName, FIL_QUERYEASIZE, (PBYTE) &eaop, sizeof(eaop), 0);

  if (!tflag && (quietflg < 2))
    printf(" (%ld bytes EA's)", pFEA2list -> cbList);

  free(pFEA2list);
}


ULONG SizeOfEAs(void *extra_field)
{
  EAHEADER *pEAblock = (PEAHEADER) extra_field;

  if ( extra_field != NULL && pEAblock -> nID == EAID )
    return pEAblock -> lSize;

  return 0;
}


#endif /* !ZIPINFO */


static unsigned char cUpperCase[256], cLowerCase[256];
static BOOL bInitialized;

static void InitNLS(void)
{
  unsigned nCnt, nU;
  COUNTRYCODE cc;

  bInitialized = TRUE;

  for ( nCnt = 0; nCnt < 256; nCnt++ )
    cUpperCase[nCnt] = cLowerCase[nCnt] = (unsigned char) nCnt;

  cc.country = cc.codepage = 0;
  DosMapCase(sizeof(cUpperCase), &cc, (PCHAR) cUpperCase);

  for ( nCnt = 0; nCnt < 256; nCnt++ )
  {
    nU = cUpperCase[nCnt];
    if (nU != nCnt && cLowerCase[nU] == (unsigned char) nU)
      cLowerCase[nU] = (unsigned char) nCnt;
  }

  for ( nCnt = 'A'; nCnt <= 'Z'; nCnt++ )
    cLowerCase[nCnt] = (unsigned char) (nCnt - 'A' + 'a');
}


int IsUpperNLS(int nChr)
{
  if (!bInitialized)
    InitNLS();
  return (cUpperCase[nChr] == (unsigned char) nChr);
}


int ToLowerNLS(int nChr)
{
  if (!bInitialized)
    InitNLS();
  return cLowerCase[nChr];
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.