home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / UNZP50P1.ZIP / OS2 / os2unzip.c < prev    next >
C/C++ Source or Header  |  1993-01-23  |  9KB  |  427 lines

  1. /* Unix/HPFS filename translation for FAT file systems */
  2. /*  (with special unzip modifications:  sflag) */
  3.  
  4. /* also includes lots of EA code for OS/2 */
  5.  
  6. /* Author: Kai Uwe Rommel */
  7.  
  8. #include "unzip.h"
  9.  
  10. #define INCL_NOPM
  11. #define INCL_DOSNLS
  12. #define INCL_DOSERRORS
  13. #define ULONG _ULONG
  14. #include <os2.h>
  15. #undef ULONG
  16.  
  17. #ifdef __WATCOMC__
  18. unsigned char __near _osmode = OS2_MODE;
  19. #endif
  20.  
  21.  
  22. #define EAID     0x0009
  23.  
  24.  
  25. extern int tflag, quietflg;
  26.  
  27.  
  28. typedef struct
  29. {
  30.   USHORT nID;
  31.   USHORT nSize;
  32.   ULONG lSize;
  33. }
  34. EAHEADER, *PEAHEADER;
  35.  
  36.  
  37. #ifndef __32BIT__
  38.  
  39. typedef struct
  40. {
  41.   ULONG oNextEntryOffset;
  42.   BYTE fEA;
  43.   BYTE cbName;
  44.   USHORT cbValue;
  45.   CHAR szName[1];
  46. }
  47. FEA2, *PFEA2;
  48.  
  49. typedef struct
  50. {
  51.   ULONG cbList;
  52.   FEA2 list[1];
  53. }
  54. FEA2LIST, *PFEA2LIST;
  55.  
  56. #endif
  57.  
  58.  
  59. #ifndef __32BIT__
  60. #define DosSetPathInfo(p1, p2, p3, p4, p5) \
  61.         DosSetPathInfo(p1, p2, p3, p4, p5, 0)
  62. #define DosQueryPathInfo(p1, p2, p3, p4) \
  63.     DosQPathInfo(p1, p2, p3, p4, 0)
  64. #define DosMapCase DosCaseMap
  65. #define DosQueryCtryInfo DosGetCtryInfo
  66. #endif
  67.  
  68.  
  69. #ifndef ZIPINFO
  70.  
  71.  
  72. extern int sflag;  /* user wants to allow spaces (e.g., "EA DATA. SF") */
  73.  
  74. void ChangeNameForFAT(char *name)
  75. {
  76.   char *src, *dst, *next, *ptr, *dot, *start;
  77.   static char invalid[] = ":;,=+\"[]<>| \t";
  78.  
  79.   if ( isalpha(name[0]) && (name[1] == ':') )
  80.     start = name + 2;
  81.   else
  82.     start = name;
  83.  
  84.   src = dst = start;
  85.   if ( (*src == '/') || (*src == '\\') )
  86.     src++, dst++;
  87.  
  88.   while ( *src )
  89.   {
  90.     for ( next = src; *next && (*next != '/') && (*next != '\\'); next++ );
  91.  
  92.     for ( ptr = src, dot = NULL; ptr < next; ptr++ )
  93.       if ( *ptr == '.' )
  94.       {
  95.         dot = ptr; /* remember last dot */
  96.         *ptr = '_';
  97.       }
  98.  
  99.     if ( dot == NULL )
  100.       for ( ptr = src; ptr < next; ptr++ )
  101.         if ( *ptr == '_' )
  102.           dot = ptr; /* remember last _ as if it were a dot */
  103.  
  104.     if ( dot && (dot > src) &&
  105.          ((next - dot <= 4) ||
  106.           ((next - src > 8) && (dot - src > 3))) )
  107.     {
  108.       if ( dot )
  109.         *dot = '.';
  110.  
  111.       for ( ptr = src; (ptr < dot) && ((ptr - src) < 8); ptr++ )
  112.         *dst++ = *ptr;
  113.  
  114.       for ( ptr = dot; (ptr < next) && ((ptr - dot) < 4); ptr++ )
  115.         *dst++ = *ptr;
  116.     }
  117.     else
  118.     {
  119.       if ( dot && (next - src == 1) )
  120.         *dot = '.';           /* special case: "." as a path component */
  121.  
  122.       for ( ptr = src; (ptr < next) && ((ptr - src) < 8); ptr++ )
  123.         *dst++ = *ptr;
  124.     }
  125.  
  126.     *dst++ = *next; /* either '/' or 0 */
  127.  
  128.     if ( *next )
  129.     {
  130.       src = next + 1;
  131.  
  132.       if ( *src == 0 ) /* handle trailing '/' on dirs ! */
  133.         *dst = 0;
  134.     }
  135.     else
  136.       break;
  137.   }
  138.  
  139.   for ( src = start; *src != 0; ++src )
  140.     if ( (strchr(invalid, *src) != NULL) ||
  141.          ((*src == ' ') && !sflag) )  /* allow spaces if user wants */
  142.         *src = '_';
  143. }
  144.  
  145.  
  146. int IsFileNameValid(char *name)
  147. {
  148.   HFILE hf;
  149. #ifdef __32BIT__
  150.   ULONG uAction;
  151. #else
  152.   USHORT uAction;
  153. #endif
  154.  
  155.   switch( DosOpen(name, &hf, &uAction, 0, 0, FILE_OPEN,
  156.                   OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, 0) )
  157.   {
  158.   case ERROR_INVALID_NAME:
  159.   case ERROR_FILENAME_EXCED_RANGE:
  160.     return FALSE;
  161.   case NO_ERROR:
  162.     DosClose(hf);
  163.   default:
  164.     return TRUE;
  165.   }
  166. }
  167.  
  168.  
  169. int GetCountryInfo(void)
  170. {
  171.     COUNTRYINFO ctryi;
  172.     COUNTRYCODE ctryc;
  173. #ifdef __32BIT__
  174.     ULONG cbInfo;
  175. #else
  176.     USHORT cbInfo;
  177. #endif
  178.  
  179.   ctryc.country = ctryc.codepage = 0;
  180.  
  181.   if ( DosQueryCtryInfo(sizeof(ctryi), &ctryc, &ctryi, &cbInfo) != NO_ERROR )
  182.     return 0;
  183.  
  184.   return ctryi.fsDateFmt;
  185. }
  186.  
  187.  
  188. long GetFileTime(char *name)
  189. {
  190. #ifdef __32BIT__
  191.   FILESTATUS3 fs;
  192. #else
  193.   FILESTATUS fs;
  194. #endif
  195.   USHORT nDate, nTime;
  196.  
  197.   if ( DosQueryPathInfo(name, 1, (PBYTE) &fs, sizeof(fs)) )
  198.     return -1;
  199.  
  200.   nDate = * (USHORT *) &fs.fdateLastWrite;
  201.   nTime = * (USHORT *) &fs.ftimeLastWrite;
  202.  
  203.   return ((ULONG) nDate) << 16 | nTime;
  204. }
  205.  
  206.  
  207. void SetPathInfo(char *path, UWORD moddate, UWORD modtime, int flags)
  208. {
  209.   union {
  210.     FDATE fd;               /* system file date record */
  211.     UWORD zdate;            /* date word */
  212.   } ud;
  213.   union {
  214.     FTIME ft;               /* system file time record */
  215.     UWORD ztime;            /* time word */
  216.   } ut;
  217.   FILESTATUS fs;
  218.   USHORT nLength;
  219.   char szName[CCHMAXPATH];
  220.  
  221.   strcpy(szName, path);
  222.   nLength = strlen(szName);
  223.   if (szName[nLength - 1] == '/')
  224.     szName[nLength - 1] = 0;
  225.  
  226.   if ( DosQueryPathInfo(szName, FIL_STANDARD, (PBYTE) &fs, sizeof(fs)) )
  227.     return;
  228.  
  229.   ud.zdate = moddate;
  230.   ut.ztime = modtime;
  231.   fs.fdateLastWrite = fs.fdateCreation = ud.fd;
  232.   fs.ftimeLastWrite = fs.ftimeCreation = ut.ft;
  233.  
  234.   if ( flags != -1 )
  235.     fs.attrFile = flags; /* hidden, system, archive, read-only */
  236.  
  237.   DosSetPathInfo(szName, FIL_STANDARD, (PBYTE) &fs, sizeof(fs), 0);
  238. }
  239.  
  240.  
  241. typedef struct
  242. {
  243.   ULONG cbList;               /* length of value + 22 */
  244. #ifdef __32BIT__
  245.   ULONG oNext;
  246. #endif
  247.   BYTE fEA;                   /* 0 */
  248.   BYTE cbName;                /* length of ".LONGNAME" = 9 */
  249.   USHORT cbValue;             /* length of value + 4 */
  250.   BYTE szName[10];            /* ".LONGNAME" */
  251.   USHORT eaType;              /* 0xFFFD for length-preceded ASCII */
  252.   USHORT eaSize;              /* length of value */
  253.   BYTE szValue[CCHMAXPATH];
  254. }
  255. FEALST;
  256.  
  257.  
  258. int SetLongNameEA(char *name, char *longname)
  259. {
  260.   EAOP eaop;
  261.   FEALST fealst;
  262.  
  263.   if ( _osmode == DOS_MODE )
  264.     return 0;
  265.  
  266.   eaop.fpFEAList = (PFEALIST) &fealst;
  267.   eaop.fpGEAList = NULL;
  268.   eaop.oError = 0;
  269.  
  270.   strcpy(fealst.szName, ".LONGNAME");
  271.   strcpy(fealst.szValue, longname);
  272.  
  273.   fealst.cbList  = sizeof(fealst) - CCHMAXPATH + strlen(fealst.szValue);
  274.   fealst.cbName  = (BYTE) strlen(fealst.szName);
  275.   fealst.cbValue = sizeof(USHORT) * 2 + strlen(fealst.szValue);
  276.  
  277. #ifdef __32BIT__
  278.   fealst.oNext   = 0;
  279. #endif
  280.   fealst.fEA     = 0;
  281.   fealst.eaType  = 0xFFFD;
  282.   fealst.eaSize  = strlen(fealst.szValue);
  283.  
  284.   return DosSetPathInfo(name, FIL_QUERYEASIZE,
  285.                         (PBYTE) &eaop, sizeof(eaop), 0);
  286. }
  287.  
  288.  
  289. int IsEA(void *extra_field)
  290. {
  291.   EAHEADER *pEAblock = (PEAHEADER) extra_field;
  292.   return extra_field != NULL && pEAblock -> nID == EAID;
  293. }
  294.  
  295.  
  296. void SetEAs(char *path, void *eablock)
  297. {
  298.   EAHEADER *pEAblock = (PEAHEADER) eablock;
  299. #ifdef __32BIT__
  300.   EAOP2 eaop;
  301.   PFEA2LIST pFEA2list;
  302. #else
  303.   EAOP eaop;
  304.   PFEALIST pFEAlist;
  305.   PFEA pFEA;
  306.   PFEA2LIST pFEA2list;
  307.   PFEA2 pFEA2;
  308.   ULONG nLength2;
  309. #endif
  310.   USHORT nLength;
  311.   char szName[CCHMAXPATH];
  312.  
  313.   if ( !IsEA(eablock) )
  314.     return;
  315.  
  316.   if ( _osmode == DOS_MODE )
  317.     return;
  318.  
  319.   strcpy(szName, path);
  320.   nLength = strlen(szName);
  321.   if (szName[nLength - 1] == '/')
  322.     szName[nLength - 1] = 0;
  323.  
  324.   if ( (pFEA2list = (PFEA2LIST) malloc((size_t) pEAblock -> lSize)) == NULL )
  325.     return;
  326.  
  327.   if ( memextract((char *) pFEA2list, pEAblock -> lSize,
  328.               (char *) (pEAblock + 1), 
  329.           pEAblock -> nSize - sizeof(pEAblock -> lSize)) )
  330.   {
  331.     free(pFEA2list);
  332.     return;
  333.   }
  334.  
  335. #ifdef __32BIT__
  336.   eaop.fpGEA2List = NULL;
  337.   eaop.fpFEA2List = pFEA2list;
  338. #else
  339.   pFEAlist  = (PVOID) pFEA2list;
  340.   pFEA2 = pFEA2list -> list;
  341.   pFEA  = pFEAlist  -> list;
  342.  
  343.   do
  344.   {
  345.     nLength2 = pFEA2 -> oNextEntryOffset;
  346.     nLength = sizeof(FEA) + pFEA2 -> cbName + 1 + pFEA2 -> cbValue;
  347.  
  348.     memcpy(pFEA, (PCH) pFEA2 + sizeof(pFEA2 -> oNextEntryOffset), nLength);
  349.  
  350.     pFEA2 = (PFEA2) ((PCH) pFEA2 + nLength2);
  351.     pFEA = (PFEA) ((PCH) pFEA + nLength);
  352.   }
  353.   while ( nLength2 != 0 );
  354.  
  355.   pFEAlist -> cbList = (PCH) pFEA - (PCH) pFEAlist;
  356.  
  357.   eaop.fpGEAList = NULL;
  358.   eaop.fpFEAList = pFEAlist;
  359. #endif
  360.  
  361.   eaop.oError = 0;
  362.   DosSetPathInfo(szName, FIL_QUERYEASIZE, (PBYTE) &eaop, sizeof(eaop), 0);
  363.  
  364.   if (!tflag && (quietflg < 2))
  365.     printf(" (%ld bytes EA's)", pFEA2list -> cbList);
  366.  
  367.   free(pFEA2list);
  368. }
  369.  
  370.  
  371. ULONG SizeOfEAs(void *extra_field)
  372. {
  373.   EAHEADER *pEAblock = (PEAHEADER) extra_field;
  374.  
  375.   if ( extra_field != NULL && pEAblock -> nID == EAID )
  376.     return pEAblock -> lSize;
  377.  
  378.   return 0;
  379. }
  380.  
  381.  
  382. #endif /* !ZIPINFO */
  383.  
  384.  
  385. static unsigned char cUpperCase[256], cLowerCase[256];
  386. static BOOL bInitialized;
  387.  
  388. static void InitNLS(void)
  389. {
  390.   unsigned nCnt, nU;
  391.   COUNTRYCODE cc;
  392.  
  393.   bInitialized = TRUE;
  394.  
  395.   for ( nCnt = 0; nCnt < 256; nCnt++ )
  396.     cUpperCase[nCnt] = cLowerCase[nCnt] = (unsigned char) nCnt;
  397.  
  398.   cc.country = cc.codepage = 0;
  399.   DosMapCase(sizeof(cUpperCase), &cc, (PCHAR) cUpperCase);
  400.  
  401.   for ( nCnt = 0; nCnt < 256; nCnt++ )
  402.   {
  403.     nU = cUpperCase[nCnt];
  404.     if (nU != nCnt && cLowerCase[nU] == (unsigned char) nU)
  405.       cLowerCase[nU] = (unsigned char) nCnt;
  406.   }
  407.  
  408.   for ( nCnt = 'A'; nCnt <= 'Z'; nCnt++ )
  409.     cLowerCase[nCnt] = (unsigned char) (nCnt - 'A' + 'a');
  410. }
  411.  
  412.  
  413. int IsUpperNLS(int nChr)
  414. {
  415.   if (!bInitialized)
  416.     InitNLS();
  417.   return (cUpperCase[nChr] == (unsigned char) nChr);
  418. }
  419.  
  420.  
  421. int ToLowerNLS(int nChr)
  422. {
  423.   if (!bInitialized)
  424.     InitNLS();
  425.   return cLowerCase[nChr];
  426. }
  427.