home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 6 File / 06-File.zip / mc454src.zip / mc-4.5.4.src / os2emx / src / glib / gutils.c < prev    next >
C/C++ Source or Header  |  1999-01-04  |  16KB  |  796 lines

  1. /* GLIB - Library of useful routines for C programming
  2.  * Copyright (C) 1995-1998  Peter Mattis, Spencer Kimball and Josh MacDonald
  3.  *
  4.  * This library is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU Library General Public
  6.  * License as published by the Free Software Foundation; either
  7.  * version 2 of the License, or (at your option) any later version.
  8.  *
  9.  * This library is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.     See the GNU
  12.  * Library General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU Library General Public
  15.  * License along with this library; if not, write to the
  16.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  17.  * Boston, MA 02111-1307, USA.
  18.  */
  19.  
  20. /* 
  21.  * MT safe for the unix part, FIXME: make the win32 part MT safe as well.
  22.  */
  23.  
  24. #ifdef HAVE_CONFIG_H
  25. #include <config.h>
  26. #endif
  27.  
  28. #include "glibconfig.h"
  29.  
  30. #ifdef HAVE_UNISTD_H
  31. #include <unistd.h>
  32. #endif
  33. #include <stdarg.h>
  34. #include <stdlib.h>
  35. #include <stdio.h>
  36. #include <string.h>
  37. #include <errno.h>
  38. #ifdef HAVE_PWD_H
  39. #include <pwd.h>
  40. #endif
  41. #include <sys/types.h>
  42. #ifdef HAVE_SYS_PARAM_H
  43. #include <sys/param.h>
  44. #endif
  45.  
  46. #ifdef NATIVE_WIN32
  47. #  define STRICT            /* Strict typing, please */
  48. #  include <windows.h>
  49. #  include <direct.h>
  50. #  include <errno.h>
  51. #  include <ctype.h>
  52. #  ifdef _MSC_VER
  53. #    include <io.h>
  54. #  endif /* _MSC_VER */
  55. #endif /* NATIVE_WIN32 */
  56.  
  57. /* implement Glib's inline functions
  58.  */
  59. #define    G_INLINE_FUNC extern
  60. #define    G_CAN_INLINE 1
  61. #include "glib.h"
  62.  
  63. #ifdef    MAXPATHLEN
  64. #define    G_PATH_LENGTH    (MAXPATHLEN + 1)
  65. #elif    defined (PATH_MAX)
  66. #define    G_PATH_LENGTH    (PATH_MAX + 1)
  67. #else    /* !MAXPATHLEN */
  68. #define G_PATH_LENGTH   (2048 + 1)
  69. #endif    /* !MAXPATHLEN && !PATH_MAX */
  70.  
  71. const guint glib_major_version = GLIB_MAJOR_VERSION;
  72. const guint glib_minor_version = GLIB_MINOR_VERSION;
  73. const guint glib_micro_version = GLIB_MICRO_VERSION;
  74. const guint glib_interface_age = GLIB_INTERFACE_AGE;
  75. const guint glib_binary_age = GLIB_BINARY_AGE;
  76.  
  77. #if defined (NATIVE_WIN32) && defined (__LCC__)
  78. int __stdcall 
  79. LibMain (void         *hinstDll,
  80.      unsigned long dwReason,
  81.      void         *reserved)
  82. {
  83.   return 1;
  84. }
  85. #endif /* NATIVE_WIN32 && __LCC__ */
  86.  
  87. void
  88. g_atexit (GVoidFunc func)
  89. {
  90.   gint result;
  91.   gchar *error = NULL;
  92.  
  93.   /* keep this in sync with glib.h */
  94.  
  95. #ifdef    G_NATIVE_ATEXIT
  96.   result = ATEXIT (func);
  97.   if (result)
  98.     error = g_strerror (errno);
  99. #elif defined (HAVE_ATEXIT)
  100. #  ifdef NeXT /* @#%@! NeXTStep */
  101.   result = !atexit ((void (*)(void)) func);
  102.   if (result)
  103.     error = g_strerror (errno);
  104. #  else
  105.   result = atexit ((void (*)(void)) func);
  106.   if (result)
  107.     error = g_strerror (errno);
  108. #  endif /* NeXT */
  109. #elif defined (HAVE_ON_EXIT)
  110.   result = on_exit ((void (*)(int, void *)) func, NULL);
  111.   if (result)
  112.     error = g_strerror (errno);
  113. #else
  114.   result = 0;
  115.   error = "no implementation";
  116. #endif /* G_NATIVE_ATEXIT */
  117.  
  118.   if (error)
  119.     g_error ("Could not register atexit() function: %s", error);
  120. }
  121.  
  122. gint
  123. g_snprintf (gchar    *str,
  124.         gulong     n,
  125.         gchar const *fmt,
  126.         ...)
  127. {
  128. #ifdef    HAVE_VSNPRINTF
  129.   va_list args;
  130.   gint retval;
  131.   
  132.   va_start (args, fmt);
  133.   retval = vsnprintf (str, n, fmt, args);
  134.   va_end (args);
  135.   
  136.   return retval;
  137. #else    /* !HAVE_VSNPRINTF */
  138.   gchar *printed;
  139.   va_list args;
  140.   
  141.   va_start (args, fmt);
  142.   printed = g_strdup_vprintf (fmt, args);
  143.   va_end (args);
  144.   
  145.   strncpy (str, printed, n);
  146.   str[n-1] = '\0';
  147.  
  148.   g_free (printed);
  149.   
  150.   return strlen (str);
  151. #endif    /* !HAVE_VSNPRINTF */
  152. }
  153.  
  154. gint
  155. g_vsnprintf (gchar     *str,
  156.          gulong      n,
  157.          gchar const *fmt,
  158.          va_list      args)
  159. {
  160. #ifdef    HAVE_VSNPRINTF
  161.   gint retval;
  162.   
  163.   retval = vsnprintf (str, n, fmt, args);
  164.   
  165.   return retval;
  166. #else    /* !HAVE_VSNPRINTF */
  167.   gchar *printed;
  168.   
  169.   printed = g_strdup_vprintf (fmt, args);
  170.   strncpy (str, printed, n);
  171.   str[n-1] = '\0';
  172.  
  173.   g_free (printed);
  174.   
  175.   return strlen (str);
  176. #endif /* !HAVE_VSNPRINTF */
  177. }
  178.  
  179. guint         
  180. g_parse_debug_string  (const gchar *string, 
  181.                GDebugKey   *keys, 
  182.                guint        nkeys)
  183. {
  184.   guint i;
  185.   guint result = 0;
  186.   
  187.   g_return_val_if_fail (string != NULL, 0);
  188.   
  189.   if (!g_strcasecmp (string, "all"))
  190.     {
  191.       for (i=0; i<nkeys; i++)
  192.     result |= keys[i].value;
  193.     }
  194.   else
  195.     {
  196.       gchar *str = g_strdup (string);
  197.       gchar *p = str;
  198.       gchar *q;
  199.       gboolean done = FALSE;
  200.       
  201.       while (*p && !done)
  202.     {
  203.       q = strchr (p, ':');
  204.       if (!q)
  205.         {
  206.           q = p + strlen(p);
  207.           done = TRUE;
  208.         }
  209.       
  210.       *q = 0;
  211.       
  212.       for (i=0; i<nkeys; i++)
  213.         if (!g_strcasecmp(keys[i].key, p))
  214.           result |= keys[i].value;
  215.       
  216.       p = q+1;
  217.     }
  218.       
  219.       g_free (str);
  220.     }
  221.   
  222.   return result;
  223. }
  224.  
  225. gchar*
  226. g_basename (const gchar       *file_name)
  227. {
  228.   register gchar *base;
  229.   
  230.   g_return_val_if_fail (file_name != NULL, NULL);
  231.   
  232.   base = strrchr (file_name, G_DIR_SEPARATOR);
  233.   if (base)
  234.     return base + 1;
  235.  
  236. #ifdef NATIVE_WIN32
  237.   if (isalpha (file_name[0]) && file_name[1] == ':')
  238.     return (gchar*) file_name + 2;
  239. #endif /* NATIVE_WIN32 */
  240.   
  241.   return (gchar*) file_name;
  242. }
  243.  
  244. gboolean
  245. g_path_is_absolute (const gchar *file_name)
  246. {
  247.   g_return_val_if_fail (file_name != NULL, FALSE);
  248.   
  249.   if (file_name[0] == G_DIR_SEPARATOR)
  250.     return TRUE;
  251.  
  252. #ifdef NATIVE_WIN32
  253.   if (isalpha (file_name[0]) && file_name[1] == ':' && file_name[2] == G_DIR_SEPARATOR)
  254.     return TRUE;
  255. #endif
  256.  
  257.   return FALSE;
  258. }
  259.  
  260. gchar*
  261. g_path_skip_root (gchar *file_name)
  262. {
  263.   g_return_val_if_fail (file_name != NULL, NULL);
  264.   
  265.   if (file_name[0] == G_DIR_SEPARATOR)
  266.     return file_name + 1;
  267.  
  268. #ifdef NATIVE_WIN32
  269.   if (isalpha (file_name[0]) && file_name[1] == ':' && file_name[2] == G_DIR_SEPARATOR)
  270.     return file_name + 3;
  271. #endif
  272.  
  273.   return NULL;
  274. }
  275.  
  276. gchar*
  277. g_dirname (const gchar       *file_name)
  278. {
  279.   register gchar *base;
  280.   register guint len;
  281.   
  282.   g_return_val_if_fail (file_name != NULL, NULL);
  283.   
  284.   base = strrchr (file_name, G_DIR_SEPARATOR);
  285.   if (!base)
  286.     return g_strdup (".");
  287.   while (base > file_name && *base == G_DIR_SEPARATOR)
  288.     base--;
  289.   len = (guint) 1 + base - file_name;
  290.   
  291.   base = g_new (gchar, len + 1);
  292.   g_memmove (base, file_name, len);
  293.   base[len] = 0;
  294.   
  295.   return base;
  296. }
  297.  
  298. gchar*
  299. g_get_current_dir (void)
  300. {
  301.   gchar *buffer;
  302.   gchar *dir;
  303.  
  304.   buffer = g_new (gchar, G_PATH_LENGTH);
  305.   *buffer = 0;
  306.   
  307.   /* We don't use getcwd(3) on SUNOS, because, it does a popen("pwd")
  308.    * and, if that wasn't bad enough, hangs in doing so.
  309.    */
  310. #if    defined (sun) && !defined (__SVR4)
  311.   dir = getwd (buffer);
  312. #else    /* !sun */
  313.   dir = getcwd (buffer, G_PATH_LENGTH - 1);
  314. #endif    /* !sun */
  315.   
  316.   if (!dir || !*buffer)
  317.     {
  318.       /* hm, should we g_error() out here?
  319.        * this can happen if e.g. "./" has mode \0000
  320.        */
  321.       buffer[0] = G_DIR_SEPARATOR;
  322.       buffer[1] = 0;
  323.     }
  324.  
  325.   dir = g_strdup (buffer);
  326.   g_free (buffer);
  327.   
  328.   return dir;
  329. }
  330.  
  331. gchar*
  332. g_getenv (const gchar *variable)
  333. {
  334. #ifndef NATIVE_WIN32
  335.   g_return_val_if_fail (variable != NULL, NULL);
  336.  
  337.   return getenv (variable);
  338. #else
  339.   gchar *v;
  340.   guint k;
  341.   static gchar *p = NULL;
  342.   static gint l;
  343.   gchar dummy[2];
  344.  
  345.   g_return_val_if_fail (variable != NULL, NULL);
  346.   
  347.   v = getenv (variable);
  348.   if (!v)
  349.     return NULL;
  350.   
  351.   /* On Windows NT, it is relatively typical that environment variables
  352.    * contain references to other environment variables. Handle that by
  353.    * calling ExpandEnvironmentStrings.
  354.    */
  355.  
  356.   /* First check how much space we need */
  357.   k = ExpandEnvironmentStrings (v, dummy, 2);
  358.   /* Then allocate that much, and actualy do the expansion */
  359.   if (p == NULL)
  360.     {
  361.       p = g_malloc (k);
  362.       l = k;
  363.     }
  364.   else if (k > l)
  365.     {
  366.       p = g_realloc (p, k);
  367.       l = k;
  368.     }
  369.   ExpandEnvironmentStrings (v, p, k);
  370.   return p;
  371. #endif
  372. }
  373.  
  374. #ifndef OS2EMX
  375.  
  376. G_LOCK_DECLARE_STATIC (g_utils_global);
  377.  
  378. static    gchar    *g_tmp_dir = NULL;
  379. static    gchar    *g_user_name = NULL;
  380. static    gchar    *g_real_name = NULL;
  381. static    gchar    *g_home_dir = NULL;
  382.  
  383. /* HOLDS: g_utils_global_lock */
  384. static void
  385. g_get_any_init (void)
  386. {
  387.   if (!g_tmp_dir)
  388.     {
  389. #ifdef HAVE_PWD_H
  390.       struct passwd *pw;
  391. #endif
  392.  
  393.       g_tmp_dir = g_strdup (g_getenv ("TMPDIR"));
  394.       if (!g_tmp_dir)
  395.     g_tmp_dir = g_strdup (g_getenv ("TMP"));
  396.       if (!g_tmp_dir)
  397.     g_tmp_dir = g_strdup (g_getenv ("TEMP"));
  398.       
  399. #ifdef P_tmpdir
  400.       if (!g_tmp_dir)
  401.     {
  402.       int k;
  403.       g_tmp_dir = g_strdup (P_tmpdir);
  404.       k = strlen (g_tmp_dir);
  405.       if (g_tmp_dir[k-1] == G_DIR_SEPARATOR)
  406.         g_tmp_dir[k-1] = '\0';
  407.     }
  408. #endif
  409.       if (!g_tmp_dir)
  410.     {
  411. #ifndef NATIVE_WIN32
  412.       g_tmp_dir = g_strdup ("/tmp");
  413. #else /* NATIVE_WIN32 */
  414.       g_tmp_dir = g_strdup ("C:\\");
  415. #endif /* NATIVE_WIN32 */
  416.     }
  417.       
  418.       g_home_dir = g_strdup (g_getenv ("HOME"));
  419.       
  420. #ifdef HAVE_PWD_H
  421.       setpwent ();
  422.       pw = getpwuid (getuid ());
  423.       endpwent ();
  424.       
  425.       if (pw)
  426.     {
  427.       g_user_name = g_strdup (pw->pw_name);
  428.       g_real_name = g_strdup (pw->pw_gecos);
  429.       if (!g_home_dir)
  430.         g_home_dir = g_strdup (pw->pw_dir);
  431.     }
  432. #else /* !HAVE_PWD_H */
  433. #  ifdef NATIVE_WIN32
  434.       {
  435.     guint len = 17;
  436.     
  437.     g_user_name = g_new (gchar, len);
  438.     
  439.     if (!GetUserName (g_user_name, &len))
  440.       {
  441.         g_free (g_user_name);
  442.         g_user_name = g_strdup ("somebody");
  443.         g_real_name = g_strdup ("Unknown");
  444.       }
  445.     else
  446.       g_real_name = g_strdup (g_user_name);
  447.       }
  448. #  else /* !NATIVE_WIN32 */
  449.       g_user_name = g_strdup ("somebody");
  450.       g_real_name = g_strdup ("Unknown");
  451.       g_home_dir = NULL;
  452. #  endif /* !NATIVE_WIN32 */
  453. #endif /* !HAVE_PWD_H */
  454.     }  
  455. }
  456.  
  457. gchar*
  458. g_get_user_name (void)
  459. {
  460.   G_LOCK (g_utils_global);
  461.   if (!g_tmp_dir)
  462.     g_get_any_init ();
  463.   G_UNLOCK (g_utils_global);
  464.   
  465.   return g_user_name;
  466. }
  467.  
  468. gchar*
  469. g_get_real_name (void)
  470. {
  471.   G_LOCK (g_utils_global);
  472.   if (!g_tmp_dir)
  473.     g_get_any_init ();
  474.   G_UNLOCK (g_utils_global);
  475.  
  476.   return g_real_name;
  477. }
  478.  
  479. /* Return the home directory of the user. If there is a HOME
  480.  * environment variable, its value is returned, otherwise use some
  481.  * system-dependent way of finding it out. If no home directory can be
  482.  * deduced, return NULL.
  483.  */
  484.  
  485. gchar*
  486. g_get_home_dir (void)
  487. {
  488.   G_LOCK (g_utils_global);
  489.   if (!g_tmp_dir)
  490.     g_get_any_init ();
  491.   G_UNLOCK (g_utils_global);
  492.   
  493.   return g_home_dir;
  494. }
  495.  
  496. /* Return a directory to be used to store temporary files. This is the
  497.  * value of the TMPDIR, TMP or TEMP environment variables (they are
  498.  * checked in that order). If none of those exist, use P_tmpdir from
  499.  * stdio.h.  If that isn't defined, return "/tmp" on POSIXly systems,
  500.  * and C:\ on Windows.
  501.  */
  502.  
  503. gchar*
  504. g_get_tmp_dir (void)
  505. {
  506.   G_LOCK (g_utils_global);
  507.   if (!g_tmp_dir)
  508.     g_get_any_init ();
  509.   G_UNLOCK (g_utils_global);
  510.   
  511.   return g_tmp_dir;
  512. }
  513.  
  514. static gchar *g_prgname = NULL;
  515.  
  516. gchar*
  517. g_get_prgname (void)
  518. {
  519.   gchar* retval;
  520.  
  521.   G_LOCK (g_utils_global);
  522.   retval = g_prgname;
  523.   G_UNLOCK (g_utils_global);
  524.  
  525.   return retval;
  526. }
  527.  
  528. void
  529. g_set_prgname (const gchar *prgname)
  530. {
  531.   gchar *c;
  532.     
  533.   G_LOCK (g_utils_global);
  534.   c = g_prgname;
  535.   g_prgname = g_strdup (prgname);
  536.   g_free (c);
  537.   G_UNLOCK (g_utils_global);
  538. }
  539.  
  540. guint
  541. g_direct_hash (gconstpointer v)
  542. {
  543.   return GPOINTER_TO_UINT (v);
  544. }
  545.  
  546. gint
  547. g_direct_equal (gconstpointer v1,
  548.         gconstpointer v2)
  549. {
  550.   return GPOINTER_TO_UINT (v1) == GPOINTER_TO_UINT (v2);
  551. }
  552.  
  553. gint
  554. g_int_equal (gconstpointer v1,
  555.          gconstpointer v2)
  556. {
  557.   return *((const gint*) v1) == *((const gint*) v2);
  558. }
  559.  
  560. guint
  561. g_int_hash (gconstpointer v)
  562. {
  563.   return *(const gint*) v;
  564. }
  565.  
  566. #if 0 /* Old IO Channels */
  567.  
  568. GIOChannel*
  569. g_iochannel_new (gint fd)
  570. {
  571.   GIOChannel *channel = g_new (GIOChannel, 1);
  572.  
  573.   channel->fd = fd;
  574.  
  575. #ifdef NATIVE_WIN32
  576.   channel->peer = 0;
  577.   channel->peer_fd = 0;
  578.   channel->offset = 0;
  579.   channel->need_wakeups = 0;
  580. #endif /* NATIVE_WIN32 */
  581.  
  582.   return channel;
  583. }
  584.  
  585. void
  586. g_iochannel_free (GIOChannel *channel)
  587. {
  588.   g_return_if_fail (channel != NULL);
  589.  
  590.   g_free (channel);
  591. }
  592.  
  593. void
  594. g_iochannel_close_and_free (GIOChannel *channel)
  595. {
  596.   g_return_if_fail (channel != NULL);
  597.  
  598.   close (channel->fd);
  599.  
  600.   g_iochannel_free (channel);
  601. }
  602.  
  603. #undef g_iochannel_wakeup_peer
  604.  
  605. void
  606. g_iochannel_wakeup_peer (GIOChannel *channel)
  607. {
  608. #ifdef NATIVE_WIN32
  609.   static guint message = 0;
  610. #endif
  611.  
  612.   g_return_if_fail (channel != NULL);
  613.  
  614. #ifdef NATIVE_WIN32
  615.   if (message == 0)
  616.     message = RegisterWindowMessage ("gdk-pipe-readable");
  617.  
  618. #  if 0
  619.   g_print ("g_iochannel_wakeup_peer: calling PostThreadMessage (%#x, %d, %d, %d)\n",
  620.        channel->peer, message, channel->peer_fd, channel->offset);
  621. #  endif
  622.   PostThreadMessage (channel->peer, message,
  623.              channel->peer_fd, channel->offset);
  624. #endif /* NATIVE_WIN32 */
  625. }
  626.  
  627. #endif /* Old IO Channels */
  628.  
  629. #ifdef NATIVE_WIN32
  630. #ifdef _MSC_VER
  631.  
  632. int
  633. gwin_ftruncate (gint  fd,
  634.         guint size)
  635. {
  636.   HANDLE hfile;
  637.   guint curpos;
  638.  
  639.   g_return_val_if_fail (fd >= 0, -1);
  640.   
  641.   hfile = (HANDLE) _get_osfhandle (fd);
  642.   curpos = SetFilePointer (hfile, 0, NULL, FILE_CURRENT);
  643.   if (curpos == 0xFFFFFFFF
  644.       || SetFilePointer (hfile, size, NULL, FILE_BEGIN) == 0xFFFFFFFF
  645.       || !SetEndOfFile (hfile))
  646.     {
  647.       gint error = GetLastError ();
  648.  
  649.       switch (error)
  650.     {
  651.     case ERROR_INVALID_HANDLE:
  652.       errno = EBADF;
  653.       break;
  654.     default:
  655.       errno = EIO;
  656.       break;
  657.     }
  658.  
  659.       return -1;
  660.     }
  661.  
  662.   return 0;
  663. }
  664.  
  665. DIR*
  666. gwin_opendir (const char *dirname)
  667. {
  668.   DIR *result;
  669.   gchar *mask;
  670.   guint k;
  671.  
  672.   g_return_val_if_fail (dirname != NULL, NULL);
  673.  
  674.   result = g_new0 (DIR, 1);
  675.   result->find_file_data = g_new0 (WIN32_FIND_DATA, 1);
  676.   result->dir_name = g_strdup (dirname);
  677.   
  678.   k = strlen (result->dir_name);
  679.   if (k && result->dir_name[k - 1] == '\\')
  680.     {
  681.       result->dir_name[k - 1] = '\0';
  682.       k--;
  683.     }
  684.   mask = g_strdup_printf ("%s\\*", result->dir_name);
  685.  
  686.   result->find_file_handle = (guint) FindFirstFile (mask,
  687.                          (LPWIN32_FIND_DATA) result->find_file_data);
  688.   g_free (mask);
  689.  
  690.   if (result->find_file_handle == (guint) INVALID_HANDLE_VALUE)
  691.     {
  692.       int error = GetLastError ();
  693.  
  694.       g_free (result->dir_name);
  695.       g_free (result->find_file_data);
  696.       g_free (result);
  697.       switch (error)
  698.     {
  699.     default:
  700.       errno = EIO;
  701.       return NULL;
  702.     }
  703.     }
  704.   result->just_opened = TRUE;
  705.  
  706.   return result;
  707. }
  708.  
  709. struct dirent*
  710. gwin_readdir (DIR *dir)
  711. {
  712.   static struct dirent result;
  713.  
  714.   g_return_val_if_fail (dir != NULL, NULL);
  715.  
  716.   if (dir->just_opened)
  717.     dir->just_opened = FALSE;
  718.   else
  719.     {
  720.       if (!FindNextFile ((HANDLE) dir->find_file_handle,
  721.              (LPWIN32_FIND_DATA) dir->find_file_data))
  722.     {
  723.       int error = GetLastError ();
  724.  
  725.       switch (error)
  726.         {
  727.         case ERROR_NO_MORE_FILES:
  728.           return NULL;
  729.         default:
  730.           errno = EIO;
  731.           return NULL;
  732.         }
  733.     }
  734.     }
  735.   strcpy (result.d_name, g_basename (((LPWIN32_FIND_DATA) dir->find_file_data)->cFileName));
  736.       
  737.   return &result;
  738. }
  739.  
  740. void
  741. gwin_rewinddir (DIR *dir)
  742. {
  743.   gchar *mask;
  744.  
  745.   g_return_if_fail (dir != NULL);
  746.  
  747.   if (!FindClose ((HANDLE) dir->find_file_handle))
  748.     g_warning ("gwin_rewinddir(): FindClose() failed\n");
  749.  
  750.   mask = g_strdup_printf ("%s\\*", dir->dir_name);
  751.   dir->find_file_handle = (guint) FindFirstFile (mask,
  752.                       (LPWIN32_FIND_DATA) dir->find_file_data);
  753.   g_free (mask);
  754.  
  755.   if (dir->find_file_handle == (guint) INVALID_HANDLE_VALUE)
  756.     {
  757.       int error = GetLastError ();
  758.  
  759.       switch (error)
  760.     {
  761.     default:
  762.       errno = EIO;
  763.       return;
  764.     }
  765.     }
  766.   dir->just_opened = TRUE;
  767. }  
  768.  
  769. gint
  770. gwin_closedir (DIR *dir)
  771. {
  772.   g_return_val_if_fail (dir != NULL, -1);
  773.  
  774.   if (!FindClose ((HANDLE) dir->find_file_handle))
  775.     {
  776.       int error = GetLastError ();
  777.  
  778.       switch (error)
  779.     {
  780.     default:
  781.       errno = EIO; return -1;
  782.     }
  783.     }
  784.  
  785.   g_free (dir->dir_name);
  786.   g_free (dir->find_file_data);
  787.   g_free (dir);
  788.  
  789.   return 0;
  790. }
  791.  
  792. #endif /* _MSC_VER */
  793.  
  794. #endif /* NATIVE_WIN32 */
  795.  
  796. #endif /* OS2EMX */