Skip to content

Instantly share code, notes, and snippets.

@lucasvr
Created July 10, 2018 11:20
Show Gist options
  • Save lucasvr/341828de1f1b05dd0643eaf08730c85a to your computer and use it in GitHub Desktop.
Save lucasvr/341828de1f1b05dd0643eaf08730c85a to your computer and use it in GitHub Desktop.
Mount remote dependencies
diff --git a/src/FindDependencies.c b/src/FindDependencies.c
index 257bfec1..6a7122ec 100644
--- a/src/FindDependencies.c
+++ b/src/FindDependencies.c
@@ -5,6 +5,7 @@
*
* Released under the GNU GPL version 2.
*/
+#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
@@ -14,11 +15,12 @@
#include <libgen.h>
#include <errno.h>
#include <sys/utsname.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
#include <ctype.h>
-#define _GNU_SOURCE
#include <getopt.h>
#ifdef __CYGWIN__
#include <sys/syslimits.h>
@@ -385,11 +387,46 @@ static bool SupportedArchitecture(const char *depname, const char *version, stru
return true;
}
+static struct remote_dependency *GetHandleFromRemoteHost(struct parse_data *data, struct search_options *options)
+{
+ pid_t pid = fork();
+ if (pid < 0) {
+ perror("fork");
+ } else if (pid == 0) {
+ char *source_path = NULL;
+ asprintf(&source_path, "%s@%s:%s/%s", getenv("USER"), options->hosts, options->goboPrograms, data->depname);
+
+ char *dest_path = NULL;
+ asprintf(&dest_path, "%s/%s", options->workdir, data->depname);
+ mkdir(dest_path, 0755);
+
+ // TODO: assert that dest_path is a valid directory in the write-layer
+ // TODO: sshfs is a terrible protocol, should move to 9p or something else
+ char *command[] = {"sshfs", "-v", source_path, dest_path, NULL};
+ execvp(command[0], command);
+ } else {
+ int ret, status = 0;
+ waitpid(pid, &status, 0);
+ ret = WIFEXITED(status) ? WEXITSTATUS(status) : 1;
+ if (ret == 0) {
+ struct remote_dependency *rd = (struct remote_dependency *) calloc(1, sizeof(struct remote_dependency));
+ if (! rd) {
+ perror("remote_dependency");
+ return NULL;
+ }
+ //rd->dp = opendir();
+ return rd;
+ }
+ }
+ return NULL;
+}
+
static char **GetVersionsFromReadDir(struct parse_data *data, struct search_options *options)
{
DIR *dp;
int num = 0;
struct dirent *entry;
+ struct remote_dependency *remote_dep = NULL;
char path[PATH_MAX];
char **versions;
@@ -399,8 +436,14 @@ static char **GetVersionsFromReadDir(struct parse_data *data, struct search_opti
snprintf(path, sizeof(path)-1, "%s/%s", options->goboPrograms, data->depname);
dp = opendir(path);
if (! dp) {
- WARN(options, "WARNING: %s: %s, ignoring dependency.\n", path, strerror(errno));
- return NULL;
+ if (options->hosts) {
+ remote_dep = GetHandleFromRemoteHost(data, options);
+ dp = remote_dep ? remote_dep->dp : NULL;
+ }
+ if (! dp) {
+ WARN(options, "WARNING: %s: %s, ignoring dependency.\n", path, strerror(errno));
+ return NULL;
+ }
}
while ((entry = readdir(dp))) {
diff --git a/src/FindDependencies.h b/src/FindDependencies.h
index 10ff0088..3fcbfeb2 100644
--- a/src/FindDependencies.h
+++ b/src/FindDependencies.h
@@ -55,9 +55,17 @@ struct search_options {
const char *dependency;
const char *depsfile;
const char *searchdir;
+ const char *hosts;
+ const char *workdir;
const char *goboPrograms;
};
+struct remote_dependency {
+ DIR *dp;
+ char *host;
+ char *mountpoint;
+};
+
// Function prototypes
struct list_head *ParseDependencies(struct search_options *options);
void FreeDependencies(struct list_head **deps);
diff --git a/src/Runner.c b/src/Runner.c
index afe12c41..21063fce 100644
--- a/src/Runner.c
+++ b/src/Runner.c
@@ -103,6 +103,7 @@ struct runner_args {
const char **dependencies; /* NULL-terminated */
char **arguments; /* Arguments to pass to executable */
char *architecture; /* Architecture of dependencies to consider */
+ char *hosts; /* Hosts to consider when looking up missing packages */
char *wrapper; /* Wrapper file */
char *workdir; /* Base work directory */
@@ -496,6 +497,8 @@ prepare_merge_string(const char *callerprogram, const char *dependencies)
options.repository = LOCAL_PROGRAMS;
options.depsfile = dependencies;
options.quiet = args.quiet;
+ options.hosts = args.hosts;
+ options.workdir = args.workdir;
options.wantedArch = args.architecture;
options.goboPrograms = GOBO_PROGRAMS_DIR;
options.noOperator = EQUAL;
@@ -1176,6 +1179,7 @@ show_usage_and_exit(char *exec, int err)
" -a, --arch=ARCH Look for dependencies built for ARCH (default: extract from ELF headers\n"
" or from Resources/Architecture, falling back to %s on failure)\n"
" -d, --dependencies=FILE Path to GoboLinux Dependencies file to use\n"
+ " -s, --hosts=HOSTS Comma separated list of hostnames where missing dependencies can be searched for\n"
" -h, --help This help\n"
" -q, --quiet Don't warn on bogus dependencies file(s)\n"
" -v, --verbose Run in verbose mode (type twice to enable debug messages)\n"
@@ -1196,6 +1200,7 @@ parse_arguments(int argc, char *argv[])
struct option long_options[] = {
{"arch", required_argument, 0, 'a'},
{"dependencies", required_argument, 0, 'd'},
+ {"hosts", required_argument, 0, 's'},
{"help", no_argument, 0, 'h'},
{"quiet", no_argument, 0, 'q'},
{"check", no_argument, 0, 'c'},
@@ -1205,7 +1210,7 @@ parse_arguments(int argc, char *argv[])
{"verbose", no_argument, 0, 'v'},
{0, 0, 0, 0 }
};
- const char *short_options = "+d:a:hcqvfER";
+ const char *short_options = "+d:a:hcqs:vfER";
bool valid = true;
int next = optind;
int num_deps = 0;
@@ -1245,6 +1250,8 @@ parse_arguments(int argc, char *argv[])
args.executable = NULL;
args.arguments = NULL;
args.architecture = NULL;
+ args.hosts = NULL;
+ args.workdir = NULL; // TODO
args.dependencies = (const char **) calloc(num_deps+1, sizeof(char *));
if (! args.dependencies)
@@ -1268,6 +1275,9 @@ parse_arguments(int argc, char *argv[])
case 'q':
args.quiet = true;
break;
+ case 's':
+ args.hosts = optarg;
+ break;
case 'E':
args.sourceenv = false;
break;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment