home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / zip22.zip / win32 / win32.c < prev    next >
C/C++ Source or Header  |  1997-08-23  |  14KB  |  532 lines

  1. /*
  2.  
  3.  Copyright (C) 1990-1997 Mark Adler, Richard B. Wales, Jean-loup Gailly,
  4.  Kai Uwe Rommel, Onno van der Linden and Igor Mandrichenko.
  5.  Permission is granted to any individual or institution to use, copy, or
  6.  redistribute this software so long as all of the original files are included,
  7.  that it is not sold for profit, and that this copyright notice is retained.
  8.  
  9. */
  10.  
  11. /*
  12.  * WIN32 specific functions for ZIP.
  13.  *
  14.  * The WIN32 version of ZIP heavily relies on the MSDOS and OS2 versions,
  15.  * since we have to do similar things to switch between NTFS, HPFS and FAT.
  16.  */
  17.  
  18.  
  19. #include "zip.h"
  20.  
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <time.h>
  24. #include <ctype.h>
  25. #include <windows.h>
  26. #ifdef __RSXNT__
  27. #  include "win32/rsxntwin.h"
  28. #endif
  29. #include "win32/win32zip.h"
  30.  
  31. #define A_RONLY    0x01
  32. #define A_HIDDEN   0x02
  33. #define A_SYSTEM   0x04
  34. #define A_LABEL    0x08
  35. #define A_DIR      0x10
  36. #define A_ARCHIVE  0x20
  37.  
  38.  
  39. #define EAID     0x0009
  40.  
  41.  
  42. #ifndef UTIL
  43.  
  44. extern int noisy;
  45.  
  46. #if 0           /* Currently, this is not used at all */
  47. #ifdef USE_EF_UT_TIME
  48. local time_t FileTime2utime(FILETIME *pft);
  49. #endif
  50. #endif /* never */
  51.  
  52.  
  53. /* FAT / HPFS detection */
  54.  
  55. int IsFileSystemOldFAT(char *dir)
  56. {
  57.   char root[4];
  58.   char vname[128];
  59.   DWORD vnamesize = sizeof(vname);
  60.   DWORD vserial;
  61.   DWORD vfnsize;
  62.   DWORD vfsflags;
  63.   char vfsname[128];
  64.   DWORD vfsnamesize = sizeof(vfsname);
  65.  
  66.     /*
  67.      * We separate FAT and HPFS+other file systems here.
  68.      * I consider other systems to be similar to HPFS/NTFS, i.e.
  69.      * support for long file names and being case sensitive to some extent.
  70.      */
  71.  
  72.     strncpy(root, dir, 3);
  73.     if ( isalpha(root[0]) && (root[1] == ':') ) {
  74.       root[0] = to_up(dir[0]);
  75.       root[2] = '\\';
  76.       root[3] = 0;
  77.     }
  78.     else {
  79.       root[0] = '\\';
  80.       root[1] = 0;
  81.     }
  82.  
  83.     if ( !GetVolumeInformation(root, vname, vnamesize,
  84.                          &vserial, &vfnsize, &vfsflags,
  85.                          vfsname, vfsnamesize)) {
  86.         fprintf(mesg, "zip diagnostic: GetVolumeInformation failed\n");
  87.         return(FALSE);
  88.     }
  89.  
  90.     return vfnsize <= 12;
  91. }
  92.  
  93. /* access mode bits and time stamp */
  94.  
  95. int GetFileMode(char *name)
  96. {
  97. DWORD dwAttr;
  98. #ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
  99.   char *ansi_name = (char *)alloca(strlen(name) + 1);
  100.  
  101.   OemToAnsi(name, ansi_name);
  102.   name = ansi_name;
  103. #endif
  104.  
  105.   dwAttr = GetFileAttributes(name);
  106.   if ( dwAttr == 0xFFFFFFFF ) {
  107.     fprintf(mesg, "zip diagnostic: GetFileAttributes failed\n");
  108.     return(0x20); /* the most likely, though why the error? security? */
  109.   }
  110.   return(
  111.           (dwAttr&FILE_ATTRIBUTE_READONLY  ? A_RONLY   :0)
  112.         | (dwAttr&FILE_ATTRIBUTE_HIDDEN    ? A_HIDDEN  :0)
  113.         | (dwAttr&FILE_ATTRIBUTE_SYSTEM    ? A_SYSTEM  :0)
  114.         | (dwAttr&FILE_ATTRIBUTE_DIRECTORY ? A_DIR     :0)
  115.         | (dwAttr&FILE_ATTRIBUTE_ARCHIVE   ? A_ARCHIVE :0));
  116. }
  117.  
  118.  
  119. #if 0           /* Currently, this is not used at all */
  120.  
  121. #ifdef USE_EF_UT_TIME
  122. #  define UNIX_TIME_ZERO_HI  0x019DB1DE
  123. #  define UNIX_TIME_ZERO_LO  0xD53E8000
  124. #  define NT_QUANTA_PER_UNIX 10000000
  125. #  define FTQUANTA_PER_UT_L  (NT_QUANTA_PER_UNIX & 0xFFFF)
  126. #  define FTQUANTA_PER_UT_H  (NT_QUANTA_PER_UNIX >> 16)
  127. #  define UNIX_TIME_UMAX_HI  0x0236485E
  128. #  define UNIX_TIME_UMAX_LO  0xD4A5E858
  129.  
  130. local time_t FileTime2utime(FILETIME *pft)
  131. {
  132. #if defined(__GNUC__) || defined(ULONG_LONG_MAX)
  133.     unsigned long long NTtime;
  134.  
  135.     NTtime = ((unsigned long long)pft->dwLowDateTime +
  136.               ((unsigned long long)pft->dwHighDateTime << 32))
  137.  
  138.     /* underflow and overflow handling */
  139.     if (NTtime <= ((unsigned long long)UNIX_TIME_ZERO_LO +
  140.                    ((unsigned long long)UNIX_TIME_ZERO_HI << 32)))
  141.         return (time_t)0;
  142.     if (NTtime >= ((unsigned long long)UNIX_TIME_UMAX_LO +
  143.                    ((unsigned long long)UNIX_TIME_UMAX_HI << 32)))
  144.         return (time_t)ULONG_MAX;
  145.  
  146.     NTtime -= ((unsigned long long)UNIX_TIME_ZERO_LO +
  147.                ((unsigned long long)UNIX_TIME_ZERO_HI << 32));
  148.     return (time_t)(NTtime / (unsigned long long)NT_QUANTA_PER_UNIX);
  149. #else /* "unsigned long long" may not be supported */
  150.     ulg rlo, rhi;
  151.     unsigned int carry = 0;
  152.     unsigned int blo, bm1, bm2, bhi;
  153.  
  154.     if ((pft->dwHighDateTime < UNIX_TIME_ZERO_HI) ||
  155.         ((pft->dwHighDateTime == UNIX_TIME_ZERO_HI) &&
  156.          (pft->dwLowDateTime <= UNIX_TIME_ZERO_LO)))
  157.         return (time_t)0;
  158.     if ((pft->dwHighDateTime > UNIX_TIME_UMAX_HI) ||
  159.         ((pft->dwHighDateTime == UNIX_TIME_UMAX_HI) &&
  160.          (pft->dwLowDateTime <= UNIX_TIME_UMAX_LO)))
  161.         return (time_t)ULONG_MAX;
  162.  
  163.     /* ... */
  164.     return (time_t)((ulg)blo + ((ulg)bhi) << 16));
  165. #endif
  166. }
  167. #endif /* USE_EF_UT_TIME */
  168.  
  169.  
  170. long GetTheFileTime(char *name, iztimes *z_ut)
  171. {
  172. HANDLE h;
  173. FILETIME Modft, Accft, Creft, lft;
  174. WORD dh, dl;
  175. #ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
  176.   char *ansi_name = (char *)alloca(strlen(name) + 1);
  177.  
  178.   OemToAnsi(name, ansi_name);
  179.   name = ansi_name;
  180. #endif
  181.  
  182.   h = CreateFile(name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  183.                  OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  184.   if ( h != INVALID_HANDLE_VALUE ) {
  185.     GetFileTime(h, &Creft, &Accft, &Modft);
  186.     CloseHandle(h);
  187. #ifdef USE_EF_UT_TIME
  188.     if (z_ut != NULL) {
  189.       z_ut->atime = FileTime2utime(&Accft);
  190.       z_ut->mtime = FileTime2utime(&Modft);
  191.       z_ut->ctime = FileTime2utime(&Creft);
  192.     }
  193. #endif
  194.     FileTimeToLocalFileTime(&ft, &lft);
  195.     FileTimeToDosDateTime(&lft, &dh, &dl);
  196.     return(dh<<16) | dl;
  197.   }
  198.   else
  199.     return 0L;
  200. }
  201.  
  202. #endif /* never */
  203.  
  204.  
  205. void ChangeNameForFAT(char *name)
  206. {
  207.   char *src, *dst, *next, *ptr, *dot, *start;
  208.   static char invalid[] = ":;,=+\"[]<>| \t";
  209.  
  210.   if ( isalpha(name[0]) && (name[1] == ':') )
  211.     start = name + 2;
  212.   else
  213.     start = name;
  214.  
  215.   src = dst = start;
  216.   if ( (*src == '/') || (*src == '\\') )
  217.     src++, dst++;
  218.  
  219.   while ( *src )
  220.   {
  221.     for ( next = src; *next && (*next != '/') && (*next != '\\'); next++ );
  222.  
  223.     for ( ptr = src, dot = NULL; ptr < next; ptr++ )
  224.       if ( *ptr == '.' )
  225.       {
  226.         dot = ptr; /* remember last dot */
  227.         *ptr = '_';
  228.       }
  229.  
  230.     if ( dot == NULL )
  231.       for ( ptr = src; ptr < next; ptr++ )
  232.         if ( *ptr == '_' )
  233.           dot = ptr; /* remember last _ as if it were a dot */
  234.  
  235.     if ( dot && (dot > src) &&
  236.          ((next - dot <= 4) ||
  237.           ((next - src > 8) && (dot - src > 3))) )
  238.     {
  239.       if ( dot )
  240.         *dot = '.';
  241.  
  242.       for ( ptr = src; (ptr < dot) && ((ptr - src) < 8); ptr++ )
  243.         *dst++ = *ptr;
  244.  
  245.       for ( ptr = dot; (ptr < next) && ((ptr - dot) < 4); ptr++ )
  246.         *dst++ = *ptr;
  247.     }
  248.     else
  249.     {
  250.       if ( dot && (next - src == 1) )
  251.         *dot = '.';           /* special case: "." as a path component */
  252.  
  253.       for ( ptr = src; (ptr < next) && ((ptr - src) < 8); ptr++ )
  254.         *dst++ = *ptr;
  255.     }
  256.  
  257.     *dst++ = *next; /* either '/' or 0 */
  258.  
  259.     if ( *next )
  260.     {
  261.       src = next + 1;
  262.  
  263.       if ( *src == 0 ) /* handle trailing '/' on dirs ! */
  264.         *dst = 0;
  265.     }
  266.     else
  267.       break;
  268.   }
  269.  
  270.   for ( src = start; *src != 0; ++src )
  271.     if ( (strchr(invalid, *src) != NULL) || (*src == ' ') )
  272.       *src = '_';
  273. }
  274.  
  275. char *GetLongPathEA(char *name)
  276. {
  277.     return(NULL); /* volunteers ? */
  278. }
  279.  
  280. int IsFileNameValid(x)
  281. char *x;
  282. {
  283.     WIN32_FIND_DATA fd;
  284.     HANDLE h;
  285. #ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
  286.     char *ansi_name = (char *)alloca(strlen(x) + 1);
  287.  
  288.     OemToAnsi(x, ansi_name);
  289.     x = ansi_name;
  290. #endif
  291.  
  292.     if ((h = FindFirstFile(x, &fd)) == INVALID_HANDLE_VALUE)
  293.         return FALSE;
  294.     FindClose(h);
  295.     return TRUE;
  296. }
  297.  
  298. char *getVolumeLabel(drive, vtime, vmode, vutim)
  299.   int drive;    /* drive name: 'A' .. 'Z' or '\0' for current drive */
  300.   ulg *vtime;   /* volume label creation time (DOS format) */
  301.   ulg *vmode;   /* volume label file mode */
  302.   time_t *vutim;/* volume label creationtime (UNIX format) */
  303.  
  304. /* If a volume label exists for the given drive, return its name and
  305.    pretend to set its time and mode. The returned name is static data. */
  306. {
  307.   char rootpath[4];
  308.   static char vol[14];
  309.   ulg fnlen, flags;
  310.  
  311.   *vmode = A_ARCHIVE | A_LABEL;           /* this is what msdos returns */
  312.   *vtime = dostime(1980, 1, 1, 0, 0, 0);  /* no true date info available */
  313.   *vutim = dos2unixtime(*vtime);
  314.   strcpy(rootpath, "x:\\");
  315.   rootpath[0] = drive;
  316.   if (GetVolumeInformation(drive ? rootpath : NULL, vol, 13, NULL,
  317.                            &fnlen, &flags, NULL, 0))
  318. #ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
  319.     return (AnsiToOem(vol, vol), vol);
  320. #else
  321.     return vol;
  322. #endif
  323.   else
  324.     return NULL;
  325. }
  326.  
  327. #endif /* !UTIL */
  328.  
  329.  
  330.  
  331. int ZipIsWinNT(void)    /* returns TRUE if real NT, FALSE if Win95 or Win32s */
  332. {
  333.     static DWORD g_PlatformId = 0xFFFFFFFF; /* saved platform indicator */
  334.  
  335.     if (g_PlatformId == 0xFFFFFFFF) {
  336.         /* note: GetVersionEx() doesn't exist on WinNT 3.1 */
  337.         if (GetVersion() < 0x80000000)
  338.             g_PlatformId = TRUE;
  339.         else
  340.             g_PlatformId = FALSE;
  341.     }
  342.     return (int)g_PlatformId;
  343. }
  344.  
  345.  
  346. #ifndef UTIL
  347. #ifdef __WATCOMC__
  348. #  include <io.h>
  349. #  define _get_osfhandle _os_handle
  350. /* gaah -- Watcom's docs claim that _get_osfhandle exists, but it doesn't.  */
  351. #endif
  352.  
  353. /*
  354.  * return TRUE if file is seekable
  355.  */
  356. int fseekable(fp)
  357. FILE *fp;
  358. {
  359.     return GetFileType((HANDLE)_get_osfhandle(fileno(fp))) == FILE_TYPE_DISK;
  360. }
  361. #endif /* !UTIL */
  362.  
  363.  
  364. #if 0 /* seems to be never used; try it out... */
  365. char *StringLower(char *szArg)
  366. {
  367.   char *szPtr;
  368. /*  unsigned char *szPtr; */
  369.   for ( szPtr = szArg; *szPtr; szPtr++ )
  370.     *szPtr = lower[*szPtr];
  371.   return szArg;
  372. }
  373. #endif /* never */
  374.  
  375.  
  376. #ifdef __WATCOMC__
  377.  
  378. /* This papers over a bug in Watcom 10.6's standard library... sigh. */
  379. /* Apparently it applies to both the DOS and Win32 stat()s.          */
  380. /* I believe this has been fixed for the following Watcom release.   */
  381.  
  382. int stat_bandaid(const char *path, struct stat *buf)
  383. {
  384.   char newname[4];
  385.   if (!stat(path, buf))
  386.     return 0;
  387.   else if (!strcmp(path, ".") || (path[0] && !strcmp(path + 1, ":."))) {
  388.     strcpy(newname, path);
  389.     newname[strlen(path) - 1] = '\\';   /* stat(".") fails for root! */
  390.     return stat(newname, buf);
  391.   } else
  392.     return -1;
  393. }
  394.  
  395. /* Watcom 10.6's getch() does not handle Alt+<digit><digit><digit>. */
  396. /* Note that if PASSWD_FROM_STDIN is defined, the file containing   */
  397. /* the password must have a carriage return after the word, not a   */
  398. /* Unix-style newline (linefeed only).  This discards linefeeds.    */
  399.  
  400. int getch(void)
  401. {
  402.   HANDLE stin;
  403.   DWORD rc;
  404.   unsigned char buf[2];
  405.   int ret = -1;
  406.  
  407. #  ifdef PASSWD_FROM_STDIN
  408.   DWORD odemode = ~0;
  409.   stin = GetStdHandle(STD_INPUT_HANDLE);
  410.   if (GetConsoleMode(stin, &odemode))
  411.     SetConsoleMode(stin, ENABLE_PROCESSED_INPUT);  /* raw except ^C noticed */
  412. #  else
  413.   if (!(stin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
  414.                           FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)))
  415.     return -1;
  416.   SetConsoleMode(stin, ENABLE_PROCESSED_INPUT);    /* raw except ^C noticed */
  417. #  endif
  418.   if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1)
  419.     ret = buf[0];
  420.   /* when the user hits return we get CR LF.  We discard the LF, not the CR,
  421.    * because when we call this for the first time after a previous input
  422.    * such as the one for "replace foo? [y]es, ..." the LF may still be in
  423.    * the input stream before whatever the user types at our prompt. */
  424.   if (ret == '\n')
  425.     if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1)
  426.       ret = buf[0];
  427. #  ifdef PASSWD_FROM_STDIN
  428.   if (odemode != ~0)
  429.     SetConsoleMode(stin, odemode);
  430. #  else
  431.   CloseHandle(stin);
  432. #  endif
  433.   return ret;
  434. }
  435. #endif /* __WATCOMC__ */
  436.  
  437.  
  438. #ifndef WINDLL
  439. /******************************/
  440. /*  Function version_local()  */
  441. /******************************/
  442.  
  443. void version_local()
  444. {
  445.     static ZCONST char CompiledWith[] = "Compiled with %s%s for %s%s%s%s.\n\n";
  446. #if defined(_MSC_VER) || defined(__WATCOMC__)
  447.     char buf[80];
  448. #if defined(_MSC_VER) && _MSC_VER > 900
  449.     char buf2[80];
  450. #endif
  451. #endif
  452.  
  453.     printf(CompiledWith,
  454.  
  455. #ifdef _MSC_VER  /* MSC == MSVC++, including the SDK compiler */
  456.       (sprintf(buf, "Microsoft C %d.%02d ", _MSC_VER/100, _MSC_VER%100), buf),
  457. #  if (_MSC_VER == 800)
  458.         "(Visual C++ v1.1)",
  459. #  elif (_MSC_VER == 850)
  460.         "(Windows NT v3.5 SDK)",
  461. #  elif (_MSC_VER == 900)
  462.         "(Visual C++ v2.x)",
  463. #  elif (_MSC_VER > 900)
  464.         (sprintf(buf2, "(Visual C++ v%d.%d)", _MSC_VER/100 - 6,
  465.                  _MSC_VER%100/10), buf2),
  466. #  else
  467.         "(bad version)",
  468. #  endif
  469. #elif defined(__WATCOMC__)
  470. #  if (__WATCOMC__ % 10 > 0)
  471. /* We do this silly test because __WATCOMC__ gives two digits for the  */
  472. /* minor version, but Watcom packaging prefers to show only one digit. */
  473.         (sprintf(buf, "Watcom C/C++ %d.%02d", __WATCOMC__ / 100,
  474.                  __WATCOMC__ % 100), buf), "",
  475. #  else
  476.         (sprintf(buf, "Watcom C/C++ %d.%d", __WATCOMC__ / 100,
  477.                  (__WATCOMC__ % 100) / 10), buf), "",
  478. #  endif /* __WATCOMC__ % 10 > 0 */
  479. #elif defined(__TURBOC__)
  480. #  ifdef __BORLANDC__
  481.      "Borland C++",
  482. #    if (__BORLANDC__ == 0x0452)   /* __BCPLUSPLUS__ = 0x0320 */
  483.         " 4.0 or 4.02",
  484. #    elif (__BORLANDC__ == 0x0460)   /* __BCPLUSPLUS__ = 0x0340 */
  485.         " 4.5",
  486. #    elif (__BORLANDC__ == 0x0500)   /* __TURBOC__ = 0x0500 */
  487.         " 5.0",
  488. #    else
  489.         " later than 5.0",
  490. #    endif
  491. #  else /* !__BORLANDC__ */
  492.      "Turbo C",
  493. #    if (__TURBOC__ >= 0x0400)     /* Kevin:  3.0 -> 0x0401 */
  494.         "++ 3.0 or later",
  495. #    elif (__TURBOC__ == 0x0295)     /* [661] vfy'd by Kevin */
  496.         "++ 1.0",
  497. #    endif
  498. #  endif /* __BORLANDC__ */
  499. #elif defined(__GNUC__)
  500. #  ifdef __RSXNT__
  501. #    if defined(__EMX__)
  502.       "rsxnt(emx)+gcc ",
  503. #    elif defined(__DJGPP__)
  504.       (sprintf(buf, "rsxnt(djgpp) v%d.%02d / gcc ", __DJGPP__, __DJGPP_MINOR__),
  505.        buf),
  506. #    elif defined(__GO32__)
  507.       "rsxnt(djgpp) v1.x / gcc ",
  508. #    else
  509.       "rsxnt(unknown) / gcc ",
  510. #    endif
  511. #  else
  512.       "gcc ",
  513. #  endif
  514.       __VERSION__,
  515. #else
  516.       "unknown compiler (SDK?)", "",
  517. #endif
  518.  
  519.       "Windows 95 / Windows NT", "\n(32-bit)",
  520.  
  521. #ifdef __DATE__
  522.       " on ", __DATE__
  523. #else
  524.       "", ""
  525. #endif
  526.     );
  527.  
  528.     return;
  529.  
  530. } /* end function version_local() */
  531. #endif /* !WINDLL */
  532.