-
Notifications
You must be signed in to change notification settings - Fork 13
/
steamfix.c
163 lines (113 loc) · 4.22 KB
/
steamfix.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
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#define _GNU_SOURCE
#include <assert.h>
#include <dlfcn.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
/* Work around timeout on login issue */
#include <sys/epoll.h>
static int (*libc_epoll_ctl)(int, int, int, struct epoll_event*) = NULL;
int epoll_ctl(int epfd, int op, int fd, struct epoll_event* event) {
if (!libc_epoll_ctl) {
libc_epoll_ctl = dlsym(RTLD_NEXT, "epoll_ctl");
}
int err = libc_epoll_ctl(epfd, op, fd, event);
if (err == -1 && op == EPOLL_CTL_MOD && errno == ENOENT) {
errno = 0;
err = libc_epoll_ctl(epfd, EPOLL_CTL_ADD, fd, event);
}
/*if (err == -1) {
perror(__func__);
}*/
return err;
}
/* Silence obnoxious "libudev: udev_monitor_new_from_netlink_fd: error getting socket: Address family not supported by protocol" warning */
void* udev_monitor_new_from_netlink(void* udev, const char* name) {
return NULL;
}
void* udev_monitor_new_from_netlink_fd(void* udev, const char *name, int fd) {
assert(0);
}
/* Do not allow Breakpad to override libSegFault handlers */
#include <execinfo.h>
#include <signal.h>
static int (*libc_sigaction)(int, const struct sigaction*, struct sigaction*) = NULL;
int sigaction(int sig, const struct sigaction* restrict act, struct sigaction* restrict oact) {
if (!libc_sigaction) {
libc_sigaction = dlsym(RTLD_NEXT, "sigaction");
}
void* buffer[2];
int nframes = backtrace(buffer, 2);
assert(nframes == 2);
char* caller_str = *backtrace_symbols(buffer + 1, 1);
assert(caller_str != NULL);
char* p = strrchr(caller_str, '/');
if (p && strncmp("crashhandler.so", p + 1, sizeof("crashhandler.so") - 1) == 0) {
return EINVAL;
}
return libc_sigaction(sig, act, oact);
}
/* Let's rewrite a few commands as well... */
static int (*libc_system)(const char*) = NULL;
#define XDG_OPEN_CMD "LD_LIBRARY_PATH=\"$SYSTEM_LD_LIBRARY_PATH\" PATH=\"$SYSTEM_PATH\" '/usr/bin/xdg-open' "
int system(const char* command) {
if (!libc_system) {
libc_system = dlsym(RTLD_NEXT, "system");
}
/* such as xdg-open */
if (strncmp(command, XDG_OPEN_CMD, sizeof(XDG_OPEN_CMD) - 1) == 0) {
char buffer[1000];
snprintf(buffer, sizeof(buffer),
"env PATH=/usr/local/bin LD_LIBRARY_PATH=\"\" LD_PRELOAD=\"\" xdg-open %s", &command[sizeof(XDG_OPEN_CMD) - 1]);
return libc_system(buffer);
}
/* or steamwebhelper, which currently crashes, so ignore it */
if (strstr(command, "steamwebhelper.sh")) {
return 1;
}
return libc_system(command);
}
/* Lie to Steam about /home being a directory. The Steam client skips symlinks in Add Library Folder / Add a (non-Steam) Gamed dialogs and,
if it was started from /home/... path, it will get quite confused without this workaround. */
#include <sys/stat.h>
static int (*libc_lxstat64)(int, const char*, struct stat64*) = NULL;
int __lxstat64(int ver, const char* path, struct stat64* stat_buf) {
if (!libc_lxstat64) {
libc_lxstat64 = dlsym(RTLD_NEXT, "__lxstat64");
}
if (strcmp(path, "//home") == 0) {
return libc_lxstat64(ver, "/usr/home", stat_buf);
} else {
return libc_lxstat64(ver, path, stat_buf);
}
}
/* Also trick Linuxulator into listing actual /usr content instead of /compat/linux/usr */
#include <dirent.h>
static int (*libc_scandir64)(const char*, struct dirent64***,
int (*)(const struct dirent64*), int (*)(const struct dirent64**, const struct dirent64**)) = NULL;
int scandir64(const char* dir, struct dirent64*** namelist,
int (*sel)(const struct dirent64*), int (*cmp)(const struct dirent64**, const struct dirent64**))
{
if (!libc_scandir64) {
libc_scandir64 = dlsym(RTLD_NEXT, "scandir64");
}
if (strcmp(dir, "/usr") == 0) {
return libc_scandir64("/usr/local/..", namelist, sel, cmp);
} else {
return libc_scandir64(dir, namelist, sel, cmp);
}
}
/* Correct uname because for whatever reason Linuxulator reports "i686" to 32-bit applications on amd64 */
#include <unistd.h>
#include <sys/utsname.h>
static int (*libc_uname)(struct utsname*) = NULL;
int uname(struct utsname* name) {
if (!libc_uname) {
libc_uname = dlsym(RTLD_NEXT, "uname");
}
int err = libc_uname(name);
if (err == 0 && access("/usr/lib64", F_OK) == 0) {
snprintf(name->machine, _UTSNAME_MACHINE_LENGTH, "x86_64");
}
return err;
}