Skip to content

Commit a64576b

Browse files
authored
Adds ENV variable that can be used to redirect /usr/include files from wrapper_open (#42)
* Redirect usr/include from open * Some renames * fix typo * Combine both redirects into a single function * Docs.md * Allow override to auto redirect of /usr/lib as well change the env var from IDO_CC to USR_LIB * PR review * Fix comment * Exit instead of silently fail * get_env_var * Fix usr/include doc comment * move comment
1 parent 5ce2654 commit a64576b

File tree

2 files changed

+103
-44
lines changed

2 files changed

+103
-44
lines changed

DOCS.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Custom Functionality
2+
3+
## Redirection
4+
IDO recomp currently has two forms of path redirection, both involving the `/usr` folder.
5+
6+
### `/usr/lib`
7+
In order for users to not having to worry about installing the binaries in particular locations in `/usr/lib`, recomp automatically redirects `/usr/lib/` paths. This is done by determining the location of `cc` and redirecting to the same directory. This does mean all the binaries and `err.english.cc` are expected to be a part of a single flattened directory.
8+
9+
It is also possible to override the auto redirect by using the environment variable `USR_LIB` with the desired redirection path. This can be used if the binaries are not in a flattened directory with `cc` or if on Linux and are unable to read `/proc/self/exe`.
10+
11+
Wrapper functions implementing this redirection:
12+
* `init_file`
13+
* `wrapper_execvp`
14+
15+
### /usr/include
16+
The other form of redirection is completely optional and is done by setting the environment variable `USR_INCLUDE` to the desired redirection path. This will than redirect all opened files files there. This is done so that the `mdebug` section file paths will still use `/usr/include` path, but the files themselves can be located elsewhere for greater flexibility.
17+
18+
Wrapper functions implementing this redirection:
19+
* `wrapper_open`

libc_impl.c

Lines changed: 84 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -187,13 +187,13 @@ static char ctype[] = {
187187
// clang-format on
188188
};
189189

190-
#define REDIRECT_USR_LIB
191190

192-
#ifdef REDIRECT_USR_LIB
193-
static char bin_dir[PATH_MAX + 1];
194-
#endif
191+
static char usr_lib_redirect[PATH_MAX + 1];
192+
static char usr_include_redirect[PATH_MAX + 1];
193+
195194
static int g_file_max = 3;
196195

196+
197197
/* Compilation Target/Emulation Host Page Size Determination */
198198
#if defined(__CYGWIN__) || (defined(__linux__) && defined(__aarch64__))
199199
#define RUNTIME_PAGESIZE
@@ -272,10 +272,32 @@ static void free_all_file_bufs(uint8_t* mem) {
272272
}
273273
}
274274

275-
static void find_bin_dir(void) {
276-
#ifdef REDIRECT_USR_LIB
277-
// gets the current executable's path
275+
void get_env_var(char* out, char* name) {
276+
char* env = getenv(name);
277+
278+
if (env == NULL) { // No environment variable found, so just return empty string
279+
out[0] = '\0';
280+
return;
281+
}
282+
283+
if (snprintf(out, PATH_MAX, "%s", env) >= PATH_MAX) {
284+
fprintf(stderr, "Error: Environment variable %s is too large\n", name);
285+
exit(1);
286+
}
287+
288+
}
289+
290+
static void init_usr_lib_redirect(void) {
278291
char path[PATH_MAX + 1] = { 0 };
292+
293+
get_env_var(path, "USR_LIB");
294+
295+
if (path[0] != '\0') {
296+
strcpy(usr_lib_redirect, path);
297+
return;
298+
}
299+
300+
// gets the current executable's path
279301
#ifdef __CYGWIN__
280302
uint32_t size = GetModuleFileName(NULL, path, PATH_MAX);
281303
if (size == 0 || size == PATH_MAX) {
@@ -289,15 +311,49 @@ static void find_bin_dir(void) {
289311
#else
290312
ssize_t size = readlink("/proc/self/exe", path, PATH_MAX);
291313
if (size < 0 || size == PATH_MAX) {
292-
char* ido_cc = NULL;
293-
if ((!(ido_cc = getenv("IDO_CC"))) || (snprintf(path, PATH_MAX, "%s", ido_cc) >= PATH_MAX)) {
294-
return;
295-
}
314+
return;
296315
}
297316
#endif
298317

299-
strcpy(bin_dir, dirname(path));
300-
#endif
318+
strcpy(usr_lib_redirect, dirname(path));
319+
}
320+
321+
static void init_usr_include_redirect(void) {
322+
char path[PATH_MAX + 1] = {0};
323+
324+
get_env_var(path, "USR_INCLUDE");
325+
326+
strcpy(usr_include_redirect, path);
327+
}
328+
329+
static void init_redirect_paths(void) {
330+
init_usr_lib_redirect();
331+
init_usr_include_redirect();
332+
}
333+
334+
/**
335+
* Redirects `path` by replacing the initial segment `from` by `to`. The result is placed in `out`.
336+
* If `path` does not have `from` as its initial segment, or there is no `to`, the original path is used.
337+
* If an error occurs, an error message will be printed, and the program exited.
338+
*/
339+
void redirect_path(char* out, const char* path, const char* from, const char* to) {
340+
int from_len = strlen(from);
341+
342+
if(!strncmp(path, from, from_len) && (to[0] != '\0')) {
343+
char redirected_path[PATH_MAX + 1] = {0};
344+
int n;
345+
346+
n = snprintf(redirected_path, sizeof(redirected_path), "%s%s", to, path + from_len);
347+
348+
if (n >= 0 && n < sizeof(redirected_path)) {
349+
strcpy(out, redirected_path);
350+
} else {
351+
fprintf(stderr, "Error: Unable to redirect %s->%s for %s\n", from, to, path);
352+
exit(1);
353+
}
354+
} else {
355+
strcpy(out, path);
356+
}
301357
}
302358

303359
void final_cleanup(uint8_t* mem) {
@@ -310,7 +366,7 @@ void final_cleanup(uint8_t* mem) {
310366
int main(int argc, char* argv[]) {
311367
int ret;
312368

313-
find_bin_dir();
369+
init_redirect_paths();
314370
#ifdef RUNTIME_PAGESIZE
315371
g_Pagesize = sysconf(_SC_PAGESIZE);
316372
#endif /* RUNTIME_PAGESIZE */
@@ -872,6 +928,10 @@ uint32_t wrapper_strlen(uint8_t* mem, uint32_t str_addr) {
872928

873929
int wrapper_open(uint8_t* mem, uint32_t pathname_addr, int flags, int mode) {
874930
STRING(pathname)
931+
932+
char rpathname[PATH_MAX + 1];
933+
redirect_path(rpathname, pathname, "/usr/include", usr_include_redirect);
934+
875935
int f = flags & O_ACCMODE;
876936
if (flags & 0x100) {
877937
f |= O_CREAT;
@@ -888,7 +948,8 @@ int wrapper_open(uint8_t* mem, uint32_t pathname_addr, int flags, int mode) {
888948
if (flags & 0x08) {
889949
f |= O_APPEND;
890950
}
891-
int fd = open(pathname, f, mode);
951+
952+
int fd = open(rpathname, f, mode);
892953
MEM_U32(ERRNO_ADDR) = errno;
893954
return fd;
894955
}
@@ -1299,17 +1360,11 @@ static uint32_t init_file(uint8_t* mem, int fd, int i, const char* path, const c
12991360
flags = O_RDWR | O_CREAT | O_APPEND;
13001361
}
13011362
if (fd == -1) {
1363+
char rpathname[PATH_MAX + 1];
1364+
redirect_path(rpathname, path, "/usr/lib", usr_lib_redirect);
1365+
1366+
fd = open(rpathname, flags, 0666);
13021367

1303-
#ifdef REDIRECT_USR_LIB
1304-
char fixed_path[PATH_MAX + 1];
1305-
if (!strcmp(path, "/usr/lib/err.english.cc") && bin_dir[0] != '\0') {
1306-
int n = snprintf(fixed_path, sizeof(fixed_path), "%s/err.english.cc", bin_dir);
1307-
if (n >= 0 && n < sizeof(fixed_path)) {
1308-
path = fixed_path;
1309-
}
1310-
}
1311-
#endif
1312-
fd = open(path, flags, 0666);
13131368
if (fd < 0) {
13141369
MEM_U32(ERRNO_ADDR) = errno;
13151370
return 0;
@@ -2637,25 +2692,10 @@ int wrapper_execvp(uint8_t* mem, uint32_t file_addr, uint32_t argv_addr) {
26372692
}
26382693
argv[argc] = NULL;
26392694

2640-
#ifdef REDIRECT_USR_LIB
2641-
if (!strncmp(file, "/usr/lib/", 9) && bin_dir[0] != '\0') {
2642-
char fixed_path[PATH_MAX + 1];
2643-
#ifdef __CYGWIN__
2644-
int n = snprintf(fixed_path, sizeof(fixed_path), "%s/%s.exe", bin_dir, file + 9);
2645-
#else
2646-
int n = snprintf(fixed_path, sizeof(fixed_path), "%s/%s", bin_dir, file + 9);
2647-
#endif
2648-
if (n > 0 && n < sizeof(fixed_path)) {
2649-
execvp(fixed_path, argv);
2650-
} else {
2651-
execvp(file, argv);
2652-
}
2653-
} else {
2654-
execvp(file, argv);
2655-
}
2656-
#else
2657-
execvp(file, argv);
2658-
#endif
2695+
char rfile[PATH_MAX + 1];
2696+
redirect_path(rfile, file, "/usr/lib", usr_lib_redirect);
2697+
2698+
execvp(rfile, argv);
26592699

26602700
MEM_U32(ERRNO_ADDR) = errno;
26612701
for (uint32_t i = 0; i < argc; i++) {

0 commit comments

Comments
 (0)