-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlibgl-switcheroo.c
93 lines (83 loc) · 2.02 KB
/
libgl-switcheroo.c
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
#define FUSE_USE_VERSION 26
#include <fuse.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define LIBNAME "/libGL.so.1"
static int sw_getattr(const char *path, struct stat *stbuf)
{
memset(stbuf, 0, sizeof(struct stat));
if (!strcmp(path, "/lib")
#ifdef LIB64PATH
|| !strcmp(path, LIB64PATH)
#endif
#ifdef LIB32PATH
|| !strcmp(path, LIB32PATH)
#endif
)
{
stbuf->st_mode = S_IFDIR | 0500;
return 0;
}
if (!strcmp(path + strlen(path) - strlen(LIBNAME), LIBNAME))
{
stbuf->st_mode = S_IFLNK | 0777;
stbuf->st_size = strlen(LIBPATH) + strlen(ALTPATH) + strlen(path);
return 0;
}
return -ENOENT;
}
static pthread_mutex_t mutex;
static struct sockaddr_un addr;
static int need_switch(pid_t p)
{
int do_switch = 0;
pthread_mutex_lock(&mutex);
int sock = socket(PF_UNIX, SOCK_STREAM, 0);
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
perror("connect");
goto unlock;
}
if (send(sock, &p, sizeof(p), 0) != sizeof(p))
{
perror("send");
goto unlock;
}
if (recv(sock, &p, sizeof(p), 0) != sizeof(p))
{
perror("send");
goto unlock;
}
do_switch = p;
unlock:
pthread_mutex_unlock(&mutex);
return do_switch;
}
static int sw_readlink(const char *path, char *buf, size_t bufsize)
{
assert(strlen(path) >= strlen(LIBNAME));
snprintf(buf, bufsize, LIBPATH "%.*s%s", (int)(strlen(path) - strlen(LIBNAME)), path,
need_switch(fuse_get_context()->pid) ? ALTPATH LIBNAME : LIBNAME);
return 0;
}
static struct fuse_operations ops = {
.getattr = sw_getattr,
.readlink = sw_readlink
};
int main(int argc, char *argv[])
{
pthread_mutex_init(&mutex, NULL);
addr.sun_family = AF_UNIX;
snprintf(addr.sun_path, sizeof(addr.sun_path), "/tmp/libgl-switcheroo-%s/socket", getenv("USER"));
return fuse_main(argc, argv, &ops, NULL);
}