2

I'm working with a build system that relies on absolute paths to reference source files etc. When I want to test building with different toolchains, I mount the src directory in VMs or chroots. The problem is that the path to my src directory on my host machine is very complex -- lets say /a/b/c/d/src -- and it has to match the mounted path.

I want to be able to mount my src directory in somewhere like /mnt/src, but I always end up needing to create a symlink /a/b/c/d/src to /mnt/src, or just have the mountpoint at /a/b/c/d/src directly.

It feels dirty to have /a/b/c/d in the filesystem, and in general you might not even have permissions to create files in /a/b/c/d (or any of the parent directories). Is there any way to fake this path to appease my build system?

tomKPZ
  • 123

2 Answers2

2

The best solution would be to teach that build system that source paths and installation paths are not the same thing, but I'll assume you can't do that.

The most straightforward method would be to arrange for the source path to be something that can be easily reproduced, such as /var/tmp/mybuild. If the build system isn't too obnoxious, making this a symbolic link to where the files are located should be enough. If the build system insists on canonicalizing symbolic links, you should be able to fool it by using a bind mount instead. With bindfs, you don't need root privileges, you only need to have write permission on the location where you want to make the files appear.

If you can't act on the source system, an alternative approach is to preload a dynamic library that redirect certain file accesses. This assumes that all the executables that will be running are linked dynamically. The code in the linked example demonstrates how to do it from a specific file; it can be tweaked to redirect all the files whose path starts with a certain prefix. Replace

if (!strcmp(path, FROM)) {
    path = TO;
}
…
return ret;

by something like (untested)

char *other_path = NULL;
if (!strncmp(path, FROM, strlen(FROM))) {
    other_path = malloc(strlen(path) - strlen(FROM) + strlen(TO) + 1);
    if (other_path == NULL) return -ENOENT; // return NULL in fopen
    memcpy(other_path, TO, strlen(TO));
    memcpy(other_path + strlen(TO), path + strlen(FROM), strlen(path) - strlen(FROM) + 1);
    path = other_path;
}
…
free(other_path);
return ret;
0

If your objective is to avoid polluting "the host" with residue from test builds, then building inside a firejail with persistent overlay should be a good option. By that approach, it would build, and maybe install, as if for real, but the files end up in an overlay rather than polluting "the real" file system.

There is the drawback that you'll need to locate test build results within the overlay, but at the same time this has the possible advantage of preserving successive test build results, e.g., for comparing them, or whatever other later forensic you might need to do.