Blame SOURCES/0001-Use-CreateFile-on-Win32-to-make-sure-g_unlink-always.patch

c8cc85
From 7f4f4354540440c0a8a37beaccbec8bc7fc15ec7 Mon Sep 17 00:00:00 2001
c8cc85
From: Erik van Pienbroek <epienbro@fedoraproject.org>
c8cc85
Date: Mon, 27 Aug 2012 23:28:54 +0200
c8cc85
Subject: [PATCH] Use CreateFile on Win32 to make sure g_unlink always works
c8cc85
c8cc85
The functions g_open(), g_creat() and g_fopen() defer to _wopen(),
c8cc85
_wcreat() and _wfopen() respectively. This is very similar to
c8cc85
the corresponding arrangement for Linux. However, those Windows
c8cc85
functions do not support renaming a file whilst it's open. As a
c8cc85
result, g_rename() behaves differently on the Windows platform
c8cc85
compared to its Linux behaviour, where files can be renamed even
c8cc85
while there are file handles still open. Resolved this by using
c8cc85
the Win32 API function CreateFile() instead of _wopen(), _wcreat()
c8cc85
and _wfopen()
c8cc85
c8cc85
Patch initially created by John Emmas
c8cc85
---
c8cc85
 glib/gstdio.c | 259 ++++++++++++++++++++++++++++++++++++++++++++++++++++------
c8cc85
 1 file changed, 233 insertions(+), 26 deletions(-)
c8cc85
c8cc85
diff --git a/glib/gstdio.c b/glib/gstdio.c
c8cc85
index 6d763e1..c1d072f 100644
c8cc85
--- a/glib/gstdio.c
c8cc85
+++ b/glib/gstdio.c
c8cc85
@@ -1045,6 +1045,11 @@ g_open (const gchar *filename,
c8cc85
 	int          mode)
c8cc85
 {
c8cc85
 #ifdef G_OS_WIN32
c8cc85
+  HANDLE hFile;
c8cc85
+  DWORD  dwDesiredAccess       = 0;
c8cc85
+  DWORD  dwFlagsAndAttributes  = 0;
c8cc85
+  DWORD  dwDisposition         = OPEN_EXISTING;
c8cc85
+  DWORD  dwSharedAccess        = FILE_SHARE_READ | FILE_SHARE_DELETE;
c8cc85
   wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
c8cc85
   int retval;
c8cc85
   int save_errno;
c8cc85
@@ -1055,12 +1060,114 @@ g_open (const gchar *filename,
c8cc85
       return -1;
c8cc85
     }
c8cc85
 
c8cc85
-  retval = _wopen (wfilename, flags, mode);
c8cc85
-  save_errno = errno;
c8cc85
+  /* Set up the access modes and other attributes */
c8cc85
+  if ((flags & _O_CREAT) && (mode & _S_IREAD))
c8cc85
+  {
c8cc85
+    if (! (mode & _S_IWRITE))
c8cc85
+      dwFlagsAndAttributes  = FILE_ATTRIBUTE_READONLY; /* Sets file to 'read only' after the file gets closed */
c8cc85
+  }
c8cc85
+  if ( !(flags & _O_ACCMODE))
c8cc85
+  {
c8cc85
+    /* Equates to _O_RDONLY */
c8cc85
+    if (flags & _O_TRUNC)
c8cc85
+	{
c8cc85
+	  errno = EINVAL;
c8cc85
+	  g_free (wfilename);
c8cc85
+	  return -1;
c8cc85
+	}
c8cc85
 
c8cc85
-  g_free (wfilename);
c8cc85
+	dwDesiredAccess |= GENERIC_READ;
c8cc85
+	dwSharedAccess  |= FILE_SHARE_WRITE;
c8cc85
+  }
c8cc85
+  if (flags & _O_WRONLY)
c8cc85
+  {
c8cc85
+    if (flags & _O_RDWR)
c8cc85
+	{
c8cc85
+	  errno = EINVAL;
c8cc85
+	  g_free (wfilename);
c8cc85
+	  return -1;
c8cc85
+	}
c8cc85
 
c8cc85
+	dwDesiredAccess |= GENERIC_WRITE;
c8cc85
+  }
c8cc85
+  if (flags & _O_RDWR)
c8cc85
+  {
c8cc85
+	dwDesiredAccess |= GENERIC_READ;
c8cc85
+	dwDesiredAccess |= GENERIC_WRITE;
c8cc85
+  }
c8cc85
+  if (flags & _O_TRUNC)
c8cc85
+  {
c8cc85
+    if (flags & _O_CREAT)
c8cc85
+	  dwDisposition = CREATE_ALWAYS;
c8cc85
+	else
c8cc85
+	  dwDisposition = TRUNCATE_EXISTING;
c8cc85
+  }
c8cc85
+  if ((flags & _O_CREAT) && !(flags & _O_TRUNC))
c8cc85
+  {
c8cc85
+    if (flags & _O_EXCL)
c8cc85
+	  dwDisposition = CREATE_NEW;
c8cc85
+	else
c8cc85
+	  dwDisposition = OPEN_ALWAYS;
c8cc85
+  }
c8cc85
+  if (flags & _O_CREAT)
c8cc85
+  {
c8cc85
+    /* Handle the other flags that can be attached to _O_CREAT */
c8cc85
+    if ((flags & _O_TEMPORARY) || (flags & _O_SHORT_LIVED))
c8cc85
+      dwFlagsAndAttributes |= FILE_ATTRIBUTE_TEMPORARY;
c8cc85
+
c8cc85
+    if (flags & _O_TEMPORARY)
c8cc85
+      dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
c8cc85
+  }
c8cc85
+  if ((flags & _O_SEQUENTIAL) || (flags & _O_APPEND))
c8cc85
+  {
c8cc85
+    dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
c8cc85
+  }
c8cc85
+  else if (flags & _O_RANDOM)
c8cc85
+  {
c8cc85
+    dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
c8cc85
+  }
c8cc85
+
c8cc85
+  if (0 == dwFlagsAndAttributes)
c8cc85
+    dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
c8cc85
+  hFile = CreateFileW(wfilename, dwDesiredAccess, dwSharedAccess, NULL, dwDisposition, dwFlagsAndAttributes, NULL);
c8cc85
+
c8cc85
+  if (INVALID_HANDLE_VALUE == hFile)
c8cc85
+  {
c8cc85
+    retval = (-1);
c8cc85
+
c8cc85
+    switch (GetLastError ())
c8cc85
+    {
c8cc85
+#define CASE(a,b) case ERROR_##a: errno = b; break
c8cc85
+      CASE (FILE_NOT_FOUND, ENOENT);
c8cc85
+      CASE (PATH_NOT_FOUND, ENOENT);
c8cc85
+      CASE (ACCESS_DENIED, EACCES);
c8cc85
+      CASE (NOT_SAME_DEVICE, EXDEV);
c8cc85
+      CASE (LOCK_VIOLATION, EACCES);
c8cc85
+      CASE (SHARING_VIOLATION, EACCES);
c8cc85
+      CASE (FILE_EXISTS, EEXIST);
c8cc85
+      CASE (ALREADY_EXISTS, EEXIST);
c8cc85
+#undef CASE
c8cc85
+      default: errno = EIO;
c8cc85
+    }
c8cc85
+  }
c8cc85
+  else
c8cc85
+    retval = _open_osfhandle((long)hFile, flags);
c8cc85
+
c8cc85
+  if ((-1) != retval)
c8cc85
+  {
c8cc85
+    /* We have a valid file handle. Set its translation mode to text or binary, as appropriate */
c8cc85
+    if ((!(flags & _O_TEXT)) && (_fmode == _O_BINARY))
c8cc85
+      _setmode(retval, _O_BINARY);
c8cc85
+    else if ((flags & _O_TEXT) || (_fmode == _O_TEXT))
c8cc85
+      _setmode(retval, _O_TEXT);
c8cc85
+    else
c8cc85
+      _setmode(retval, _O_BINARY);
c8cc85
+  }
c8cc85
+
c8cc85
+  save_errno = errno;
c8cc85
+  g_free (wfilename);
c8cc85
   errno = save_errno;
c8cc85
+
c8cc85
   return retval;
c8cc85
 #else
c8cc85
   int fd;
c8cc85
@@ -1108,6 +1215,8 @@ g_creat (const gchar *filename,
c8cc85
 	 int          mode)
c8cc85
 {
c8cc85
 #ifdef G_OS_WIN32
c8cc85
+  HANDLE hFile;
c8cc85
+  DWORD  dwFlagsAndAttributes  = FILE_ATTRIBUTE_NORMAL;
c8cc85
   wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
c8cc85
   int retval;
c8cc85
   int save_errno;
c8cc85
@@ -1118,12 +1227,41 @@ g_creat (const gchar *filename,
c8cc85
       return -1;
c8cc85
     }
c8cc85
 
c8cc85
-  retval = _wcreat (wfilename, mode);
c8cc85
-  save_errno = errno;
c8cc85
+  if (mode & _S_IREAD)
c8cc85
+  {
c8cc85
+    if (! (mode & _S_IWRITE))
c8cc85
+      dwFlagsAndAttributes  = FILE_ATTRIBUTE_READONLY; /* Sets file to 'read only' after the file gets closed */
c8cc85
+  }
c8cc85
 
c8cc85
-  g_free (wfilename);
c8cc85
+  hFile = CreateFileW(wfilename, (GENERIC_READ | GENERIC_WRITE), (FILE_SHARE_READ | FILE_SHARE_DELETE),
c8cc85
+                                  NULL, CREATE_ALWAYS, dwFlagsAndAttributes, NULL);
c8cc85
+
c8cc85
+  if (INVALID_HANDLE_VALUE == hFile)
c8cc85
+  {
c8cc85
+    retval = (-1);
c8cc85
+
c8cc85
+    switch (GetLastError ())
c8cc85
+    {
c8cc85
+#define CASE(a,b) case ERROR_##a: errno = b; break
c8cc85
+      CASE (FILE_NOT_FOUND, ENOENT);
c8cc85
+      CASE (PATH_NOT_FOUND, ENOENT);
c8cc85
+      CASE (ACCESS_DENIED, EACCES);
c8cc85
+      CASE (NOT_SAME_DEVICE, EXDEV);
c8cc85
+      CASE (LOCK_VIOLATION, EACCES);
c8cc85
+      CASE (SHARING_VIOLATION, EACCES);
c8cc85
+      CASE (FILE_EXISTS, EEXIST);
c8cc85
+      CASE (ALREADY_EXISTS, EEXIST);
c8cc85
+#undef CASE
c8cc85
+      default: errno = EIO;
c8cc85
+    }
c8cc85
+  }
c8cc85
+  else
c8cc85
+    retval = _open_osfhandle((long)hFile, _O_RDWR);
c8cc85
 
c8cc85
+  save_errno = errno;
c8cc85
+  g_free (wfilename);
c8cc85
   errno = save_errno;
c8cc85
+
c8cc85
   return retval;
c8cc85
 #else
c8cc85
   return creat (filename, mode);
c8cc85
@@ -1565,34 +1703,102 @@ g_fopen (const gchar *filename,
c8cc85
 	 const gchar *mode)
c8cc85
 {
c8cc85
 #ifdef G_OS_WIN32
c8cc85
-  wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
c8cc85
-  wchar_t *wmode;
c8cc85
-  FILE *retval;
c8cc85
-  int save_errno;
c8cc85
-
c8cc85
-  if (wfilename == NULL)
c8cc85
-    {
c8cc85
-      errno = EINVAL;
c8cc85
-      return NULL;
c8cc85
-    }
c8cc85
-
c8cc85
-  wmode = g_utf8_to_utf16 (mode, -1, NULL, NULL, NULL);
c8cc85
-
c8cc85
-  if (wmode == NULL)
c8cc85
-    {
c8cc85
-      g_free (wfilename);
c8cc85
-      errno = EINVAL;
c8cc85
-      return NULL;
c8cc85
-    }
c8cc85
-
c8cc85
-  _g_win32_fix_mode (wmode);
c8cc85
-  retval = _wfopen (wfilename, wmode);
c8cc85
-  save_errno = errno;
c8cc85
-
c8cc85
-  g_free (wfilename);
c8cc85
-  g_free (wmode);
c8cc85
-
c8cc85
-  errno = save_errno;
c8cc85
+  int   hFile;
c8cc85
+  int   flags  = 0;
c8cc85
+  gchar priv_mode[4];
c8cc85
+  FILE *retval = NULL;
c8cc85
+
c8cc85
+  if ((NULL == filename) || (NULL == mode))
c8cc85
+  {
c8cc85
+    errno = EINVAL;
c8cc85
+    goto out;
c8cc85
+  }
c8cc85
+  if ((strlen(mode) < 1) || (strlen(mode) > 3))
c8cc85
+  {
c8cc85
+    errno - EINVAL;
c8cc85
+    goto out;
c8cc85
+  }
c8cc85
+
c8cc85
+  strncpy(priv_mode, mode, 3);
c8cc85
+  priv_mode[3] = '\0';
c8cc85
+
c8cc85
+  /* Set up any flags to pass to 'g_open()' */
c8cc85
+  if (3 == strlen(priv_mode))
c8cc85
+  {
c8cc85
+    if (('c' == priv_mode[2]) || ('n' == priv_mode[2]))
c8cc85
+      priv_mode[2] = '\0';
c8cc85
+    else
c8cc85
+     {
c8cc85
+      if (0 == strcmp(priv_mode, "a+b"))
c8cc85
+        flags = _O_RDWR | _O_CREAT | _O_APPEND | _O_BINARY;
c8cc85
+      else if (0 == strcmp(priv_mode, "a+t"))
c8cc85
+        flags = _O_RDWR | _O_CREAT | _O_APPEND | _O_TEXT;
c8cc85
+      else if (0 == strcmp(priv_mode, "r+b"))
c8cc85
+        flags = _O_RDWR | _O_BINARY;
c8cc85
+      else if (0 == strcmp(priv_mode, "r+t"))
c8cc85
+        flags = _O_RDWR | _O_TEXT;
c8cc85
+      else if (0 == strcmp(priv_mode, "w+b"))
c8cc85
+        flags = _O_RDWR | _O_CREAT |_O_TRUNC | _O_BINARY;
c8cc85
+      else if (0 == strcmp(priv_mode, "w+t"))
c8cc85
+        flags = _O_RDWR | _O_CREAT |_O_TRUNC | _O_TEXT;
c8cc85
+      else
c8cc85
+	  {
c8cc85
+	    errno = EINVAL;
c8cc85
+        goto out;
c8cc85
+	  }
c8cc85
+     }
c8cc85
+  }
c8cc85
+  if (2 == strlen(priv_mode))
c8cc85
+  {
c8cc85
+    if (('c' == priv_mode[1]) || ('n' == priv_mode[1]))
c8cc85
+      priv_mode[1] = '\0';
c8cc85
+    else
c8cc85
+     {
c8cc85
+      if (0 == strcmp(priv_mode, "a+"))
c8cc85
+        flags = _O_RDWR | _O_CREAT | _O_APPEND;
c8cc85
+      else if (0 == strcmp(priv_mode, "ab"))
c8cc85
+        flags = _O_WRONLY | _O_CREAT | _O_APPEND | _O_BINARY;
c8cc85
+      else if (0 == strcmp(priv_mode, "at"))
c8cc85
+        flags = _O_WRONLY | _O_CREAT | _O_APPEND | _O_TEXT;
c8cc85
+      else if (0 == strcmp(priv_mode, "rb"))
c8cc85
+        flags = _O_RDONLY | _O_BINARY;
c8cc85
+      else if (0 == strcmp(priv_mode, "rt"))
c8cc85
+        flags = _O_RDONLY | _O_TEXT;
c8cc85
+      else if (0 == strcmp(priv_mode, "wb"))
c8cc85
+        flags = _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY;
c8cc85
+      else if (0 == strcmp(priv_mode, "wt"))
c8cc85
+        flags = _O_WRONLY | _O_CREAT | _O_TRUNC | _O_TEXT;
c8cc85
+      else
c8cc85
+	  {
c8cc85
+	    errno = EINVAL;
c8cc85
+        goto out;
c8cc85
+	  }
c8cc85
+     }
c8cc85
+  }
c8cc85
+  if (1 == strlen(priv_mode))
c8cc85
+  {
c8cc85
+    if (0 == strcmp(priv_mode, "a"))
c8cc85
+      flags = _O_WRONLY | _O_CREAT | _O_APPEND;
c8cc85
+    else if (0 == strcmp(priv_mode, "r"))
c8cc85
+      flags = _O_RDONLY;
c8cc85
+    else if (0 == strcmp(priv_mode, "w"))
c8cc85
+      flags = _O_WRONLY | _O_CREAT | _O_TRUNC;
c8cc85
+    else if ( !((0 == strcmp(priv_mode, "c")) || (0 == strcmp(priv_mode, "n"))))
c8cc85
+	{
c8cc85
+	  errno = EINVAL;
c8cc85
+      goto out;
c8cc85
+	}
c8cc85
+  }
c8cc85
+ 
c8cc85
+  hFile = g_open (filename, flags, (_S_IREAD | _S_IWRITE));
c8cc85
+ 
c8cc85
+  if (INVALID_HANDLE_VALUE == (HANDLE)hFile)
c8cc85
+    /* 'errno' will have already been set by 'g_open()' */
c8cc85
+    retval = NULL;
c8cc85
+  else
c8cc85
+    retval = _fdopen(hFile, mode);
c8cc85
+ 
c8cc85
+out:
c8cc85
   return retval;
c8cc85
 #else
c8cc85
   return fopen (filename, mode);
c8cc85
-- 
c8cc85
1.7.11.4
c8cc85