|
|
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 |
|