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

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