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

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