Package: wine-development / 4.2-4

fixes/temporary-directory.patch Patch series | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
description: safer selection of the temporary directory for wineserver
author: Michael Gilbert <mgilbert@debian.org>
bug-debian: https://bugs.debian.org/903622
bug-debian: https://bugs.debian.org/904041
bug-upstream: https://bugs.winehq.org/show_bug.cgi?id=39013

--- a/libs/wine/config.c
+++ b/libs/wine/config.c
@@ -25,6 +25,7 @@
 #include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
+#include <dirent.h>
 #include <errno.h>
 #include <sys/stat.h>
 #ifdef HAVE_UNISTD_H
@@ -43,7 +44,7 @@
 #include "wine/library.h"
 
 static const char server_config_dir[] = "/.wine";        /* config dir relative to $HOME */
-static const char server_root_prefix[] = "/tmp/.wine";   /* prefix for server root dir */
+static const char server_root_prefix[] = "/run/user";    /* prefix for server root dir */
 static const char server_dir_prefix[] = "/server-";      /* prefix for server dir */
 
 static char *bindir;
@@ -242,15 +243,113 @@ static char *get_runtime_argvdir( const
 /* initialize the server directory value */
 static void init_server_dir( dev_t dev, ino_t ino )
 {
-    char *p, *root;
+    char *p, *prefix = NULL, *root = NULL;
 
 #ifdef __ANDROID__  /* there's no /tmp dir on Android */
     root = build_path( config_dir, ".wineserver" );
-#elif defined(HAVE_GETUID)
-    root = xmalloc( sizeof(server_root_prefix) + 12 );
-    sprintf( root, "%s-%u", server_root_prefix, getuid() );
 #else
-    root = xstrdup( server_root_prefix );
+
+#if defined(HAVE_GETUID)
+    /* use /run/user/$uid as wineserver's tmpdir if possible */
+    prefix = xmalloc( sizeof(server_root_prefix) + 12 );
+    sprintf( prefix, "%s/%u", server_root_prefix, getuid() );
+    if (opendir( prefix ))
+    {
+        root = xmalloc( sizeof(server_root_prefix) + 17 );
+        sprintf( root, "%s/wine", prefix );
+    }
+    free( prefix );
+#endif
+
+    /* otherwise, use a randomly named directory under TMPDIR */
+    if (!root)
+    {
+        int error;
+        FILE *stream;
+        char *wineserver_file, *tmp_env, *tmp_dir;
+        mode_t mode = S_IRUSR;
+
+        /* determine the temporary directory */
+        tmp_env = secure_getenv("TMPDIR");
+        if (tmp_env)
+        {
+            tmp_dir = xmalloc( strlen(tmp_env) + 1 );
+            strcpy( tmp_dir, tmp_env );
+        }
+        else
+        {
+            const char tmp_default[] = "/tmp";
+            tmp_dir = xmalloc( sizeof(tmp_default) );
+            strcpy( tmp_dir, tmp_default );
+        }
+
+        /* remove existing wineserver tmpdir file if permissions are wrong */
+        wineserver_file = build_path( config_dir, "wineserver" );
+        if ( access( wineserver_file, F_OK ) != -1 )
+        {
+            struct stat statbuf;
+            mode_t mode_mask = S_IRWXU | S_IRWXG | S_IRWXO;
+            error = stat( wineserver_file, &statbuf );
+            if (error != 0)
+                fatal_error("error reading wineserver tmpdir file permissions\n");
+            if ((statbuf.st_mode & mode_mask) != mode)
+            {
+                error = remove( wineserver_file );
+                if (error != 0)
+                    fatal_error("error removing wineserver tmpdir file\n");
+            }
+        }
+
+        /* create or read the name of the directory */
+        stream = fopen( wineserver_file, "r" );
+        if (!stream)
+        {
+            int n, fd;
+
+            /* create a new randomized name for the directory */
+            root = mkdtemp( build_path( tmp_dir, "wine-XXXXXX" ) );
+            if (!root)
+                fatal_error("unable to create wineserver tmpdir\n");
+
+            /* save location of the chosen temporary directory */
+            fd = creat( wineserver_file, mode );
+            if (fd < 0)
+                fatal_error("error opening file descriptor for wineserver tmpdir file\n");
+            stream = fdopen( fd, "w" );
+            if (!stream)
+                fatal_error("error opening wineserver tmpdir file\n");
+            n = fputs( root + strlen(tmp_dir) + 1, stream );
+            if (n < 0)
+                fatal_error("error writing to wineserver tmpdir file\n");
+            error = fclose( stream );
+            if (error != 0)
+                fatal_error("error closing wineserver tmpdir file\n");
+        }
+        else
+        {
+            char *tmp_wineserver;
+            size_t length = 0;
+            ssize_t nread;
+
+            /* try to read a previously generated wineserver tmpdir */
+            nread = getline( &tmp_wineserver, &length, stream );
+            error = fclose( stream );
+            if (error != 0)
+                fatal_error("error closing wineserver tmpdir file\n");
+
+            /* if something went wrong, remove the broken file */
+            if (nread < 0)
+            {
+                remove( wineserver_file );
+                fatal_error("fixed a temporary directory error, please try running the same command again\n");
+            }
+
+            /* build the full path to the temporary directory */
+            root = build_path( tmp_dir, tmp_wineserver );
+        }
+        free( tmp_dir );
+        free( wineserver_file );
+    }
 #endif
 
     server_dir = xmalloc( strlen(root) + sizeof(server_dir_prefix) + 2*sizeof(dev) + 2*sizeof(ino) + 2 );