lol
1#define _GNU_SOURCE
2#include <stdio.h>
3#include <stdarg.h>
4#include <stdlib.h>
5#include <dlfcn.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <fcntl.h>
9#include <limits.h>
10#include <string.h>
11
12#define MAX_REDIRECTS 128
13
14static int nrRedirects = 0;
15static char * from[MAX_REDIRECTS];
16static char * to[MAX_REDIRECTS];
17
18// FIXME: might run too late.
19static void init() __attribute__((constructor));
20
21static void init()
22{
23 char * spec = getenv("NIX_REDIRECTS");
24 if (!spec) return;
25
26 unsetenv("NIX_REDIRECTS");
27
28 char * spec2 = malloc(strlen(spec) + 1);
29 strcpy(spec2, spec);
30
31 char * pos = spec2, * eq;
32 while ((eq = strchr(pos, '='))) {
33 *eq = 0;
34 from[nrRedirects] = pos;
35 pos = eq + 1;
36 to[nrRedirects] = pos;
37 nrRedirects++;
38 if (nrRedirects == MAX_REDIRECTS) break;
39 char * end = strchr(pos, ':');
40 if (!end) break;
41 *end = 0;
42 pos = end + 1;
43 }
44
45}
46
47static const char * rewrite(const char * path, char * buf)
48{
49 for (int n = 0; n < nrRedirects; ++n) {
50 int len = strlen(from[n]);
51 if (strncmp(path, from[n], len) != 0) continue;
52 if (snprintf(buf, PATH_MAX, "%s%s", to[n], path + len) >= PATH_MAX)
53 abort();
54 return buf;
55 }
56
57 return path;
58}
59
60/* The following set of Glibc library functions is very incomplete -
61 it contains only what we needed for programs in Nixpkgs. Just add
62 more functions as needed. */
63
64int open(const char * path, int flags, ...)
65{
66 int (*open_real) (const char *, int, mode_t) = dlsym(RTLD_NEXT, "open");
67 mode_t mode = 0;
68 if (flags & O_CREAT) {
69 va_list ap;
70 va_start(ap, flags);
71 mode = va_arg(ap, mode_t);
72 va_end(ap);
73 }
74 char buf[PATH_MAX];
75 return open_real(rewrite(path, buf), flags, mode);
76}
77
78int open64(const char * path, int flags, ...)
79{
80 int (*open64_real) (const char *, int, mode_t) = dlsym(RTLD_NEXT, "open64");
81 mode_t mode = 0;
82 if (flags & O_CREAT) {
83 va_list ap;
84 va_start(ap, flags);
85 mode = va_arg(ap, mode_t);
86 va_end(ap);
87 }
88 char buf[PATH_MAX];
89 return open64_real(rewrite(path, buf), flags, mode);
90}
91
92FILE * fopen(const char * path, const char * mode)
93{
94 FILE * (*fopen_real) (const char *, const char *) = dlsym(RTLD_NEXT, "fopen");
95 char buf[PATH_MAX];
96 return fopen_real(rewrite(path, buf), mode);
97}
98
99int __xstat(int ver, const char * path, struct stat * st)
100{
101 int (*__xstat_real) (int ver, const char *, struct stat *) = dlsym(RTLD_NEXT, "__xstat");
102 char buf[PATH_MAX];
103 return __xstat_real(ver, rewrite(path, buf), st);
104}
105
106int * access(const char * path, int mode)
107{
108 int * (*access_real) (const char *, int mode) = dlsym(RTLD_NEXT, "access");
109 char buf[PATH_MAX];
110 return access_real(rewrite(path, buf), mode);
111}