提交 35a9f27c 编写于 作者: J Jonathan Calmels

Add support for CUDA forward compatibility

上级 ebed710b
...@@ -29,9 +29,6 @@ ...@@ -29,9 +29,6 @@
#include "utils.h" #include "utils.h"
#include "xfuncs.h" #include "xfuncs.h"
#define SONAME_LIBCUDA "libcuda.so.1"
#define SONAME_LIBNVML "libnvidia-ml.so.1"
#define MAX_DEVICES 64 #define MAX_DEVICES 64
#define REAP_TIMEOUT_MS 10 #define REAP_TIMEOUT_MS 10
......
...@@ -18,6 +18,9 @@ SVCXPRT *svcunixfd_create(int, u_int, u_int); ...@@ -18,6 +18,9 @@ SVCXPRT *svcunixfd_create(int, u_int, u_int);
#include "error.h" #include "error.h"
#define SONAME_LIBCUDA "libcuda.so.1"
#define SONAME_LIBNVML "libnvidia-ml.so.1"
#define SOCK_CLT 0 #define SOCK_CLT 0
#define SOCK_SVC 1 #define SOCK_SVC 1
......
...@@ -77,6 +77,7 @@ struct nvc_container_config { ...@@ -77,6 +77,7 @@ struct nvc_container_config {
char *bins_dir; char *bins_dir;
char *libs_dir; char *libs_dir;
char *libs32_dir; char *libs32_dir;
char *cudart_dir;
char *ldconfig; char *ldconfig;
}; };
......
...@@ -26,6 +26,7 @@ static char *cgroup_root(char *, char *, const char *); ...@@ -26,6 +26,7 @@ static char *cgroup_root(char *, char *, const char *);
static char *parse_proc_file(struct error *, const char *, parse_fn, char *, const char *); static char *parse_proc_file(struct error *, const char *, parse_fn, char *, const char *);
static char *find_cgroup_path(struct error *, const struct nvc_container *, const char *); static char *find_cgroup_path(struct error *, const struct nvc_container *, const char *);
static char *find_namespace_path(struct error *, const struct nvc_container *, const char *); static char *find_namespace_path(struct error *, const struct nvc_container *, const char *);
static int find_library_paths(struct error *, struct nvc_container *);
static int lookup_owner(struct error *, struct nvc_container *); static int lookup_owner(struct error *, struct nvc_container *);
static int copy_config(struct error *, struct nvc_container *, const struct nvc_container_config *); static int copy_config(struct error *, struct nvc_container *, const struct nvc_container_config *);
...@@ -180,6 +181,48 @@ find_namespace_path(struct error *err, const struct nvc_container *cnt, const ch ...@@ -180,6 +181,48 @@ find_namespace_path(struct error *err, const struct nvc_container *cnt, const ch
return (ns); return (ns);
} }
static int
find_library_paths(struct error *err, struct nvc_container *cnt)
{
char path[PATH_MAX];
glob_t gl;
int rv = -1;
char **ptr;
if (!(cnt->flags & OPT_COMPUTE_LIBS))
return (0);
if (path_join(err, path, cnt->cfg.rootfs, cnt->cfg.cudart_dir) < 0)
return (-1);
if (path_append(err, path, "compat/lib*.so.*") < 0)
return (-1);
if (xglob(err, path, GLOB_ERR, NULL, &gl) < 0)
goto fail;
if (gl.gl_pathc > 0) {
cnt->nlibs = gl.gl_pathc;
cnt->libs = ptr = array_new(err, gl.gl_pathc);
if (cnt->libs == NULL)
goto fail;
for (size_t i = 0; i < gl.gl_pathc; ++i) {
if (path_resolve(err, path, cnt->cfg.rootfs, gl.gl_pathv[i] + strlen(cnt->cfg.rootfs)) < 0)
goto fail;
if (!str_array_match(path, (const char * const *)cnt->libs, (size_t)(ptr - cnt->libs))) {
log_infof("selecting %s%s", cnt->cfg.rootfs, path);
if ((*ptr++ = xstrdup(err, path)) == NULL)
goto fail;
}
}
array_pack(cnt->libs, &cnt->nlibs);
}
rv = 0;
fail:
globfree(&gl);
return (rv);
}
static int static int
lookup_owner(struct error *err, struct nvc_container *cnt) lookup_owner(struct error *err, struct nvc_container *cnt)
{ {
...@@ -205,6 +248,7 @@ copy_config(struct error *err, struct nvc_container *cnt, const struct nvc_conta ...@@ -205,6 +248,7 @@ copy_config(struct error *err, struct nvc_container *cnt, const struct nvc_conta
const char *bins_dir = cfg->bins_dir; const char *bins_dir = cfg->bins_dir;
const char *libs_dir = cfg->libs_dir; const char *libs_dir = cfg->libs_dir;
const char *libs32_dir = cfg->libs32_dir; const char *libs32_dir = cfg->libs32_dir;
const char *cudart_dir = cfg->cudart_dir;
const char *ldconfig = cfg->ldconfig; const char *ldconfig = cfg->ldconfig;
char *rootfs; char *rootfs;
int multiarch, ret; int multiarch, ret;
...@@ -266,6 +310,8 @@ copy_config(struct error *err, struct nvc_container *cnt, const struct nvc_conta ...@@ -266,6 +310,8 @@ copy_config(struct error *err, struct nvc_container *cnt, const struct nvc_conta
} }
} }
} }
if (cudart_dir == NULL)
cudart_dir = CUDA_RUNTIME_DIR;
if (ldconfig == NULL) { if (ldconfig == NULL) {
/* /*
* Some distributions have a wrapper script around ldconfig to reduce package install time. * Some distributions have a wrapper script around ldconfig to reduce package install time.
...@@ -284,6 +330,8 @@ copy_config(struct error *err, struct nvc_container *cnt, const struct nvc_conta ...@@ -284,6 +330,8 @@ copy_config(struct error *err, struct nvc_container *cnt, const struct nvc_conta
goto fail; goto fail;
if ((cnt->cfg.libs32_dir = xstrdup(err, libs32_dir)) == NULL) if ((cnt->cfg.libs32_dir = xstrdup(err, libs32_dir)) == NULL)
goto fail; goto fail;
if ((cnt->cfg.cudart_dir = xstrdup(err, cudart_dir)) == NULL)
goto fail;
if ((cnt->cfg.ldconfig = xstrdup(err, ldconfig)) == NULL) if ((cnt->cfg.ldconfig = xstrdup(err, ldconfig)) == NULL)
goto fail; goto fail;
rv = 0; rv = 0;
...@@ -302,7 +350,7 @@ nvc_container_new(struct nvc_context *ctx, const struct nvc_container_config *cf ...@@ -302,7 +350,7 @@ nvc_container_new(struct nvc_context *ctx, const struct nvc_container_config *cf
if (validate_context(ctx) < 0) if (validate_context(ctx) < 0)
return (NULL); return (NULL);
if (validate_args(ctx, cfg != NULL && cfg->pid > 0 && cfg->rootfs != NULL && !str_empty(cfg->rootfs) && cfg->rootfs[0] == '/' && if (validate_args(ctx, cfg != NULL && cfg->pid > 0 && cfg->rootfs != NULL && !str_empty(cfg->rootfs) && cfg->rootfs[0] == '/' &&
!str_empty(cfg->bins_dir) && !str_empty(cfg->libs_dir) && !str_empty(cfg->libs32_dir) && !str_empty(cfg->ldconfig)) < 0) !str_empty(cfg->bins_dir) && !str_empty(cfg->libs_dir) && !str_empty(cfg->libs32_dir) && !str_empty(cfg->cudart_dir) && !str_empty(cfg->ldconfig)) < 0)
return (NULL); return (NULL);
if (opts == NULL) if (opts == NULL)
opts = default_container_opts; opts = default_container_opts;
...@@ -322,6 +370,10 @@ nvc_container_new(struct nvc_context *ctx, const struct nvc_container_config *cf ...@@ -322,6 +370,10 @@ nvc_container_new(struct nvc_context *ctx, const struct nvc_container_config *cf
goto fail; goto fail;
if (lookup_owner(&ctx->err, cnt) < 0) if (lookup_owner(&ctx->err, cnt) < 0)
goto fail; goto fail;
if (!(flags & OPT_NO_CNTLIBS)) {
if (find_library_paths(&ctx->err, cnt) < 0)
goto fail;
}
if ((cnt->mnt_ns = find_namespace_path(&ctx->err, cnt, "mnt")) == NULL) if ((cnt->mnt_ns = find_namespace_path(&ctx->err, cnt, "mnt")) == NULL)
goto fail; goto fail;
if (!(flags & OPT_NO_CGROUPS)) { if (!(flags & OPT_NO_CGROUPS)) {
...@@ -335,6 +387,7 @@ nvc_container_new(struct nvc_context *ctx, const struct nvc_container_config *cf ...@@ -335,6 +387,7 @@ nvc_container_new(struct nvc_context *ctx, const struct nvc_container_config *cf
log_infof("setting bins directory to %s", cnt->cfg.bins_dir); log_infof("setting bins directory to %s", cnt->cfg.bins_dir);
log_infof("setting libs directory to %s", cnt->cfg.libs_dir); log_infof("setting libs directory to %s", cnt->cfg.libs_dir);
log_infof("setting libs32 directory to %s", cnt->cfg.libs32_dir); log_infof("setting libs32 directory to %s", cnt->cfg.libs32_dir);
log_infof("setting cudart directory to %s", cnt->cfg.cudart_dir);
log_infof("setting ldconfig to %s%s", cnt->cfg.ldconfig, (cnt->cfg.ldconfig[0] == '@') ? " (host relative)" : ""); log_infof("setting ldconfig to %s%s", cnt->cfg.ldconfig, (cnt->cfg.ldconfig[0] == '@') ? " (host relative)" : "");
log_infof("setting mount namespace to %s", cnt->mnt_ns); log_infof("setting mount namespace to %s", cnt->mnt_ns);
if (!(flags & OPT_NO_CGROUPS)) if (!(flags & OPT_NO_CGROUPS))
...@@ -355,8 +408,10 @@ nvc_container_free(struct nvc_container *cnt) ...@@ -355,8 +408,10 @@ nvc_container_free(struct nvc_container *cnt)
free(cnt->cfg.bins_dir); free(cnt->cfg.bins_dir);
free(cnt->cfg.libs_dir); free(cnt->cfg.libs_dir);
free(cnt->cfg.libs32_dir); free(cnt->cfg.libs32_dir);
free(cnt->cfg.cudart_dir);
free(cnt->cfg.ldconfig); free(cnt->cfg.ldconfig);
free(cnt->mnt_ns); free(cnt->mnt_ns);
free(cnt->dev_cg); free(cnt->dev_cg);
array_free(cnt->libs, cnt->nlibs);
free(cnt); free(cnt);
} }
...@@ -134,7 +134,7 @@ select_libraries(struct error *err, void *ptr, const char *root, const char *ori ...@@ -134,7 +134,7 @@ select_libraries(struct error *err, void *ptr, const char *root, const char *ori
/* Check the driver version. */ /* Check the driver version. */
if ((rv = str_has_suffix(lib, info->nvrm_version)) == false) if ((rv = str_has_suffix(lib, info->nvrm_version)) == false)
goto done; goto done;
if (str_array_match(lib, graphics_libs_compat, nitems(graphics_libs_compat))) { if (str_array_match_prefix(lib, graphics_libs_compat, nitems(graphics_libs_compat))) {
/* Only choose OpenGL/EGL libraries issued by NVIDIA. */ /* Only choose OpenGL/EGL libraries issued by NVIDIA. */
if ((rv = elftool_has_dependency(&et, "libnvidia-glcore.so")) != false) if ((rv = elftool_has_dependency(&et, "libnvidia-glcore.so")) != false)
goto done; goto done;
...@@ -394,9 +394,9 @@ lookup_ipcs(struct error *err, struct nvc_driver_info *info, const char *root, i ...@@ -394,9 +394,9 @@ lookup_ipcs(struct error *err, struct nvc_driver_info *info, const char *root, i
bool bool
match_binary_flags(const char *bin, int32_t flags) match_binary_flags(const char *bin, int32_t flags)
{ {
if ((flags & OPT_UTILITY_BINS) && str_array_match(bin, utility_bins, nitems(utility_bins))) if ((flags & OPT_UTILITY_BINS) && str_array_match_prefix(bin, utility_bins, nitems(utility_bins)))
return (true); return (true);
if ((flags & OPT_COMPUTE_BINS) && str_array_match(bin, compute_bins, nitems(compute_bins))) if ((flags & OPT_COMPUTE_BINS) && str_array_match_prefix(bin, compute_bins, nitems(compute_bins)))
return (true); return (true);
return (false); return (false);
} }
...@@ -404,15 +404,15 @@ match_binary_flags(const char *bin, int32_t flags) ...@@ -404,15 +404,15 @@ match_binary_flags(const char *bin, int32_t flags)
bool bool
match_library_flags(const char *lib, int32_t flags) match_library_flags(const char *lib, int32_t flags)
{ {
if ((flags & OPT_UTILITY_LIBS) && str_array_match(lib, utility_libs, nitems(utility_libs))) if ((flags & OPT_UTILITY_LIBS) && str_array_match_prefix(lib, utility_libs, nitems(utility_libs)))
return (true); return (true);
if ((flags & OPT_COMPUTE_LIBS) && str_array_match(lib, compute_libs, nitems(compute_libs))) if ((flags & OPT_COMPUTE_LIBS) && str_array_match_prefix(lib, compute_libs, nitems(compute_libs)))
return (true); return (true);
if ((flags & OPT_VIDEO_LIBS) && str_array_match(lib, video_libs, nitems(video_libs))) if ((flags & OPT_VIDEO_LIBS) && str_array_match_prefix(lib, video_libs, nitems(video_libs)))
return (true); return (true);
if ((flags & OPT_GRAPHICS_LIBS) && (str_array_match(lib, graphics_libs, nitems(graphics_libs)) || if ((flags & OPT_GRAPHICS_LIBS) && (str_array_match_prefix(lib, graphics_libs, nitems(graphics_libs)) ||
str_array_match(lib, graphics_libs_glvnd, nitems(graphics_libs_glvnd)) || str_array_match_prefix(lib, graphics_libs_glvnd, nitems(graphics_libs_glvnd)) ||
str_array_match(lib, graphics_libs_compat, nitems(graphics_libs_compat)))) str_array_match_prefix(lib, graphics_libs_compat, nitems(graphics_libs_compat))))
return (true); return (true);
return (false); return (false);
} }
......
...@@ -36,6 +36,8 @@ ...@@ -36,6 +36,8 @@
#define NV_UVM_PROC_DRIVER "/proc/driver/nvidia-uvm" #define NV_UVM_PROC_DRIVER "/proc/driver/nvidia-uvm"
#define NV_APP_PROFILE_DIR "/etc/nvidia/nvidia-application-profiles-rc.d" #define NV_APP_PROFILE_DIR "/etc/nvidia/nvidia-application-profiles-rc.d"
#define CUDA_RUNTIME_DIR "/usr/local/cuda"
struct nvc_context { struct nvc_context {
bool initialized; bool initialized;
struct error err; struct error err;
...@@ -51,6 +53,8 @@ struct nvc_container { ...@@ -51,6 +53,8 @@ struct nvc_container {
gid_t gid; gid_t gid;
char *mnt_ns; char *mnt_ns;
char *dev_cg; char *dev_cg;
char **libs;
size_t nlibs;
}; };
enum { enum {
......
...@@ -33,6 +33,7 @@ static void unmount(const char *); ...@@ -33,6 +33,7 @@ static void unmount(const char *);
static int setup_cgroup(struct error *, const char *, dev_t); static int setup_cgroup(struct error *, const char *, dev_t);
static int symlink_library(struct error *, const char *, const char *, const char *, uid_t, gid_t); static int symlink_library(struct error *, const char *, const char *, const char *, uid_t, gid_t);
static int symlink_libraries(struct error *, const struct nvc_container *, const char * const [], size_t); static int symlink_libraries(struct error *, const struct nvc_container *, const char * const [], size_t);
static void filter_libraries(const struct nvc_driver_info *, char * [], size_t *);
static char ** static char **
mount_files(struct error *err, const char *root, const struct nvc_container *cnt, const char *dir, char *paths[], size_t size) mount_files(struct error *err, const char *root, const struct nvc_container *cnt, const char *dir, char *paths[], size_t size)
...@@ -397,7 +398,7 @@ symlink_libraries(struct error *err, const struct nvc_container *cnt, const char ...@@ -397,7 +398,7 @@ symlink_libraries(struct error *err, const struct nvc_container *cnt, const char
lib = basename(paths[i]); lib = basename(paths[i]);
if (str_has_prefix(lib, "libcuda.so")) { if (str_has_prefix(lib, "libcuda.so")) {
/* XXX Many applications wrongly assume that libcuda.so exists (e.g. with dlopen). */ /* XXX Many applications wrongly assume that libcuda.so exists (e.g. with dlopen). */
if (symlink_library(err, paths[i], lib, "libcuda.so", cnt->uid, cnt->gid) < 0) if (symlink_library(err, paths[i], SONAME_LIBCUDA, "libcuda.so", cnt->uid, cnt->gid) < 0)
return (-1); return (-1);
} else if (str_has_prefix(lib, "libGLX_nvidia.so")) { } else if (str_has_prefix(lib, "libGLX_nvidia.so")) {
/* XXX GLVND requires this symlink for indirect GLX support. */ /* XXX GLVND requires this symlink for indirect GLX support. */
...@@ -408,6 +409,27 @@ symlink_libraries(struct error *err, const struct nvc_container *cnt, const char ...@@ -408,6 +409,27 @@ symlink_libraries(struct error *err, const struct nvc_container *cnt, const char
return (0); return (0);
} }
static void
filter_libraries(const struct nvc_driver_info *info, char * paths[], size_t *size)
{
char *lib, *maj;
/*
* XXX Filter out any library that matches the major version of RM to prevent us from
* running into an unsupported configurations (e.g. CUDA compat on Geforce or non-LTS drivers).
*/
for (size_t i = 0; i < *size; ++i) {
lib = basename(paths[i]);
if ((maj = strstr(lib, ".so.")) != NULL) {
maj += strlen(".so.");
if (strncmp(info->nvrm_version, maj, strspn(maj, "0123456789")))
continue;
}
paths[i] = NULL;
}
array_pack(paths, size);
}
int int
nvc_driver_mount(struct nvc_context *ctx, const struct nvc_container *cnt, const struct nvc_driver_info *info) nvc_driver_mount(struct nvc_context *ctx, const struct nvc_container *cnt, const struct nvc_driver_info *info)
{ {
...@@ -423,7 +445,7 @@ nvc_driver_mount(struct nvc_context *ctx, const struct nvc_container *cnt, const ...@@ -423,7 +445,7 @@ nvc_driver_mount(struct nvc_context *ctx, const struct nvc_container *cnt, const
if (ns_enter(&ctx->err, cnt->mnt_ns, CLONE_NEWNS) < 0) if (ns_enter(&ctx->err, cnt->mnt_ns, CLONE_NEWNS) < 0)
return (-1); return (-1);
nmnt = 2 + info->nbins + info->nlibs + info->nlibs32 + info->nipcs + info->ndevs; nmnt = 2 + info->nbins + info->nlibs + cnt->nlibs + info->nlibs32 + info->nipcs + info->ndevs;
mnt = ptr = (const char **)array_new(&ctx->err, nmnt); mnt = ptr = (const char **)array_new(&ctx->err, nmnt);
if (mnt == NULL) if (mnt == NULL)
goto fail; goto fail;
...@@ -431,12 +453,14 @@ nvc_driver_mount(struct nvc_context *ctx, const struct nvc_container *cnt, const ...@@ -431,12 +453,14 @@ nvc_driver_mount(struct nvc_context *ctx, const struct nvc_container *cnt, const
/* Procfs mount */ /* Procfs mount */
if ((*ptr++ = mount_procfs(&ctx->err, ctx->cfg.root, cnt)) == NULL) if ((*ptr++ = mount_procfs(&ctx->err, ctx->cfg.root, cnt)) == NULL)
goto fail; goto fail;
/* Application profile mount */ /* Application profile mount */
if (cnt->flags & OPT_GRAPHICS_LIBS) { if (cnt->flags & OPT_GRAPHICS_LIBS) {
if ((*ptr++ = mount_app_profile(&ctx->err, cnt)) == NULL) if ((*ptr++ = mount_app_profile(&ctx->err, cnt)) == NULL)
goto fail; goto fail;
} }
/* Binary and library mounts */
/* Host binary and library mounts */
if (info->bins != NULL && info->nbins > 0) { if (info->bins != NULL && info->nbins > 0) {
if ((tmp = (const char **)mount_files(&ctx->err, ctx->cfg.root, cnt, cnt->cfg.bins_dir, info->bins, info->nbins)) == NULL) if ((tmp = (const char **)mount_files(&ctx->err, ctx->cfg.root, cnt, cnt->cfg.bins_dir, info->bins, info->nbins)) == NULL)
goto fail; goto fail;
...@@ -457,6 +481,24 @@ nvc_driver_mount(struct nvc_context *ctx, const struct nvc_container *cnt, const ...@@ -457,6 +481,24 @@ nvc_driver_mount(struct nvc_context *ctx, const struct nvc_container *cnt, const
} }
if (symlink_libraries(&ctx->err, cnt, mnt, (size_t)(ptr - mnt)) < 0) if (symlink_libraries(&ctx->err, cnt, mnt, (size_t)(ptr - mnt)) < 0)
goto fail; goto fail;
/* Container library mounts */
if (cnt->libs != NULL && cnt->nlibs > 0) {
size_t nlibs = cnt->nlibs;
char **libs = array_copy(&ctx->err, (const char * const *)cnt->libs, cnt->nlibs);
if (libs == NULL)
goto fail;
filter_libraries(info, libs, &nlibs);
if ((tmp = (const char **)mount_files(&ctx->err, cnt->cfg.rootfs, cnt, cnt->cfg.libs_dir, libs, nlibs)) == NULL) {
free(libs);
goto fail;
}
ptr = array_append(ptr, tmp, array_size(tmp));
free(tmp);
free(libs);
}
/* IPC mounts */ /* IPC mounts */
for (size_t i = 0; i < info->nipcs; ++i) { for (size_t i = 0; i < info->nipcs; ++i) {
/* XXX Only utility libraries require persistenced IPC, everything else is compute only. */ /* XXX Only utility libraries require persistenced IPC, everything else is compute only. */
...@@ -468,6 +510,7 @@ nvc_driver_mount(struct nvc_context *ctx, const struct nvc_container *cnt, const ...@@ -468,6 +510,7 @@ nvc_driver_mount(struct nvc_context *ctx, const struct nvc_container *cnt, const
if ((*ptr++ = mount_ipc(&ctx->err, ctx->cfg.root, cnt, info->ipcs[i])) == NULL) if ((*ptr++ = mount_ipc(&ctx->err, ctx->cfg.root, cnt, info->ipcs[i])) == NULL)
goto fail; goto fail;
} }
/* Device mounts */ /* Device mounts */
for (size_t i = 0; i < info->ndevs; ++i) { for (size_t i = 0; i < info->ndevs; ++i) {
/* XXX Only compute libraries require specific devices (e.g. UVM). */ /* XXX Only compute libraries require specific devices (e.g. UVM). */
......
...@@ -55,17 +55,18 @@ enum { ...@@ -55,17 +55,18 @@ enum {
OPT_STANDALONE = 1 << 1, OPT_STANDALONE = 1 << 1,
OPT_NO_CGROUPS = 1 << 2, OPT_NO_CGROUPS = 1 << 2,
OPT_NO_DEVBIND = 1 << 3, OPT_NO_DEVBIND = 1 << 3,
OPT_UTILITY_LIBS = 1 << 4, OPT_NO_CNTLIBS = 1 << 4,
OPT_COMPUTE_LIBS = 1 << 5, OPT_UTILITY_LIBS = 1 << 5,
OPT_VIDEO_LIBS = 1 << 6, OPT_COMPUTE_LIBS = 1 << 6,
OPT_GRAPHICS_LIBS = 1 << 7, OPT_VIDEO_LIBS = 1 << 7,
OPT_DISPLAY = 1 << 8, OPT_GRAPHICS_LIBS = 1 << 8,
OPT_UTILITY_BINS = 1 << 9, OPT_DISPLAY = 1 << 9,
OPT_COMPUTE_BINS = 1 << 10, OPT_UTILITY_BINS = 1 << 10,
OPT_COMPUTE_BINS = 1 << 11,
#if defined(__powerpc64__) /* ppc64le doesn't support compat32. */ #if defined(__powerpc64__) /* ppc64le doesn't support compat32. */
OPT_COMPAT32 = 1 << 0, OPT_COMPAT32 = 1 << 0,
#else #else
OPT_COMPAT32 = 1 << 11, OPT_COMPAT32 = 1 << 12,
#endif /* defined(__powerpc64__) */ #endif /* defined(__powerpc64__) */
}; };
...@@ -74,6 +75,7 @@ static const struct option container_opts[] = { ...@@ -74,6 +75,7 @@ static const struct option container_opts[] = {
{"standalone", OPT_STANDALONE}, {"standalone", OPT_STANDALONE},
{"no-cgroups", OPT_NO_CGROUPS}, {"no-cgroups", OPT_NO_CGROUPS},
{"no-devbind", OPT_NO_DEVBIND}, {"no-devbind", OPT_NO_DEVBIND},
{"no-cntlibs", OPT_NO_CNTLIBS},
{"utility", OPT_UTILITY_BINS|OPT_UTILITY_LIBS}, {"utility", OPT_UTILITY_BINS|OPT_UTILITY_LIBS},
{"compute", OPT_COMPUTE_BINS|OPT_COMPUTE_LIBS}, {"compute", OPT_COMPUTE_BINS|OPT_COMPUTE_LIBS},
{"video", OPT_VIDEO_LIBS|OPT_COMPUTE_LIBS}, {"video", OPT_VIDEO_LIBS|OPT_COMPUTE_LIBS},
......
...@@ -172,7 +172,7 @@ str_empty(const char *str) ...@@ -172,7 +172,7 @@ str_empty(const char *str)
} }
bool bool
str_array_match(const char *str, const char * const arr[], size_t size) str_array_match_prefix(const char *str, const char * const arr[], size_t size)
{ {
for (size_t i = 0; i < size; ++i) { for (size_t i = 0; i < size; ++i) {
if (str_has_prefix(str, arr[i])) if (str_has_prefix(str, arr[i]))
...@@ -181,6 +181,16 @@ str_array_match(const char *str, const char * const arr[], size_t size) ...@@ -181,6 +181,16 @@ str_array_match(const char *str, const char * const arr[], size_t size)
return (false); return (false);
} }
bool
str_array_match(const char *str, const char * const arr[], size_t size)
{
for (size_t i = 0; i < size; ++i) {
if (str_equal(str, arr[i]))
return (true);
}
return (false);
}
int int
str_join(struct error *err, char **s1, const char *s2, const char *sep) str_join(struct error *err, char **s1, const char *s2, const char *sep)
{ {
...@@ -327,7 +337,7 @@ ns_enter(struct error *err, const char *path, int nstype) ...@@ -327,7 +337,7 @@ ns_enter(struct error *err, const char *path, int nstype)
char ** char **
array_new(struct error *err, size_t size) array_new(struct error *err, size_t size)
{ {
char **arr = NULL; char **arr;
arr = xcalloc(err, size, sizeof(*arr)); arr = xcalloc(err, size, sizeof(*arr));
return (arr); return (arr);
...@@ -350,6 +360,17 @@ array_append(const char **ptr, const char * const arr[], size_t size) ...@@ -350,6 +360,17 @@ array_append(const char **ptr, const char * const arr[], size_t size)
return (ptr + size); return (ptr + size);
} }
char **
array_copy(struct error *err, const char * const arr[], size_t size)
{
char **ptr;
if ((ptr = array_new(err, size)) == NULL)
return (NULL);
array_append((const char **)ptr, arr, size);
return (ptr);
}
void void
array_pack(char *arr[], size_t *size) array_pack(char *arr[], size_t *size)
{ {
......
...@@ -49,6 +49,7 @@ bool str_case_equal(const char *, const char *); ...@@ -49,6 +49,7 @@ bool str_case_equal(const char *, const char *);
bool str_has_prefix(const char *, const char *); bool str_has_prefix(const char *, const char *);
bool str_has_suffix(const char *, const char *); bool str_has_suffix(const char *, const char *);
bool str_empty(const char *); bool str_empty(const char *);
bool str_array_match_prefix(const char *, const char * const [], size_t);
bool str_array_match(const char *, const char * const [], size_t); bool str_array_match(const char *, const char * const [], size_t);
int str_to_pid(struct error *, const char *, pid_t *); int str_to_pid(struct error *, const char *, pid_t *);
int str_to_ugid(struct error *, char *, uid_t *, gid_t *); int str_to_ugid(struct error *, char *, uid_t *, gid_t *);
...@@ -60,6 +61,7 @@ int ns_enter(struct error *, const char *, int); ...@@ -60,6 +61,7 @@ int ns_enter(struct error *, const char *, int);
char **array_new(struct error *, size_t); char **array_new(struct error *, size_t);
void array_free(char *[], size_t); void array_free(char *[], size_t);
void array_pack(char *[], size_t *); void array_pack(char *[], size_t *);
char **array_copy(struct error *, const char * const [], size_t);
size_t array_size(const char * const []); size_t array_size(const char * const []);
const char **array_append(const char **, const char * const [], size_t); const char **array_append(const char **, const char * const [], size_t);
......
...@@ -10,7 +10,9 @@ ...@@ -10,7 +10,9 @@
#include <sys/types.h> #include <sys/types.h>
#include <dlfcn.h> #include <dlfcn.h>
#include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <glob.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
...@@ -30,6 +32,7 @@ static inline void *xdlopen(struct error *, const char *, int); ...@@ -30,6 +32,7 @@ static inline void *xdlopen(struct error *, const char *, int);
static inline int xdlclose(struct error *, void *); static inline int xdlclose(struct error *, void *);
static inline int xmount(struct error *, const char *, const char *, static inline int xmount(struct error *, const char *, const char *,
const char *, unsigned long, const void *); const char *, unsigned long, const void *);
static inline int xglob(struct error *, const char *, int, int (*)(const char *, int), glob_t *);
#include "error.h" #include "error.h"
...@@ -154,4 +157,21 @@ xmount(struct error *err, const char *source, const char *target, ...@@ -154,4 +157,21 @@ xmount(struct error *err, const char *source, const char *target,
return (rv); return (rv);
} }
static inline int
xglob(struct error *err, const char *pattern, int flags, int (*errfn)(const char *, int), glob_t *pglob)
{
int rv;
rv = glob(pattern, flags, errfn, pglob);
if (rv != 0 && rv != GLOB_NOMATCH && errno != ENOENT) {
error_set(err, "glob search failed: %s", pattern);
return (-1);
}
if (rv != 0) {
pglob->gl_pathc = 0;
pglob->gl_pathv = NULL;
}
return (0);
}
#endif /* HEADER_XFUNCS_H */ #endif /* HEADER_XFUNCS_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册