Introduce a new read-only API to get a path where to store temporary sockets: this is different than tmpdir, as we need short paths for sockets (due to sockaddr_un::sun_path), and is either XDG_RUNTIME_DIR if set, or /tmp.
Adapt guestfs_int_create_socketname to create sockets in that location, checking whether the resulting path still fits in the limited buffer. Furthermore, print sockdir and XDG_RUNTIME_DIR in test-tool for debugging. --- fish/guestfish.pod | 11 +++++++++++ generator/actions.ml | 16 ++++++++++++++++ src/guestfs-internal.h | 7 ++++++- src/handle.c | 9 ++++++++- src/launch.c | 10 ++++++++-- src/tmpdirs.c | 33 +++++++++++++++++++++++++++++++++ test-tool/test-tool.c | 6 ++++++ 7 files changed, 88 insertions(+), 4 deletions(-) diff --git a/fish/guestfish.pod b/fish/guestfish.pod index c6f5663..bbeea82 100644 --- a/fish/guestfish.pod +++ b/fish/guestfish.pod @@ -1519,6 +1519,17 @@ about kernel selection, see L<supermin(1)>. See L</LIBGUESTFS_CACHEDIR>, L</LIBGUESTFS_TMPDIR>. +=item XDG_RUNTIME_DIR + +This directory represents a user-specific directory for storing +non-essential runtime files. + +If it is set, then is used to store temporary sockets. Otherwise, +F</tmp> is used. + +See also L</get-sockdir>, +L<http://www.freedesktop.org/wiki/Specifications/basedir-spec/>. + =back =head1 FILES diff --git a/generator/actions.ml b/generator/actions.ml index 24c6eb7..5b6898c 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -3504,6 +3504,22 @@ call it returns a simple true/false boolean result, instead of throwing an exception if a feature is not found. For other documentation see C<guestfs_available>." }; + { defaults with + name = "get_sockdir"; added = (1, 33, 8); + style = RString "sockdir", [], []; + blocking = false; + shortdesc = "get the temporary directory for sockets"; + longdesc = "\ +Get the directory used by the handle to store temporary socket files. + +This is different than C<guestfs_tmpdir>, as we need shorter paths for +sockets (due to the limited buffers of filenames for UNIX sockets), +and C<guestfs_tmpdir> may be too long for them. + +The environment variable C<XDG_RUNTIME_DIR> controls the default +value: If C<XDG_RUNTIME_DIR> is set, then that is the default. +Else F</tmp> is the default." }; + ] (* daemon_functions are any functions which cause some action diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h index bff9f64..6e441e4 100644 --- a/src/guestfs-internal.h +++ b/src/guestfs-internal.h @@ -434,8 +434,10 @@ struct guestfs_h * handle, you have to call guestfs_int_lazy_make_tmpdir. */ char *tmpdir; - /* Environment variables that affect tmpdir/cachedir locations. */ + char *sockdir; + /* Environment variables that affect tmpdir/cachedir/sockdir locations. */ char *env_tmpdir; /* $TMPDIR (NULL if not set) */ + char *env_runtimedir; /* $XDG_RUNTIME_DIR (NULL if not set)*/ char *int_tmpdir; /* $LIBGUESTFS_TMPDIR or guestfs_set_tmpdir or NULL */ char *int_cachedir; /* $LIBGUESTFS_CACHEDIR or guestfs_set_cachedir or NULL */ @@ -757,8 +759,11 @@ extern void guestfs_int_call_callbacks_array (guestfs_h *g, uint64_t event, cons /* tmpdirs.c */ extern int guestfs_int_set_env_tmpdir (guestfs_h *g, const char *tmpdir); +extern int guestfs_int_set_env_runtimedir (guestfs_h *g, const char *runtimedir); extern int guestfs_int_lazy_make_tmpdir (guestfs_h *g); +extern int guestfs_int_lazy_make_sockdir (guestfs_h *g); extern void guestfs_int_remove_tmpdir (guestfs_h *g); +extern void guestfs_int_remove_sockdir (guestfs_h *g); extern void guestfs_int_recursive_remove_dir (guestfs_h *g, const char *dir); /* whole-file.c */ diff --git a/src/handle.c b/src/handle.c index 947818c..25d3c99 100644 --- a/src/handle.c +++ b/src/handle.c @@ -273,6 +273,10 @@ parse_environment (guestfs_h *g, return -1; } + str = do_getenv (data, "XDG_RUNTIME_DIR"); + if (guestfs_int_set_env_runtimedir (g, str) == -1) + return -1; + return 0; } @@ -347,8 +351,9 @@ guestfs_close (guestfs_h *g) if (g->test_fp != NULL) fclose (g->test_fp); - /* Remove temporary directory. */ + /* Remove temporary directories. */ guestfs_int_remove_tmpdir (g); + guestfs_int_remove_sockdir (g); /* Mark the handle as dead and then free up all memory. */ g->state = NO_HANDLE; @@ -377,7 +382,9 @@ guestfs_close (guestfs_h *g) if (g->pda) hash_free (g->pda); free (g->tmpdir); + free (g->sockdir); free (g->env_tmpdir); + free (g->env_runtimedir); free (g->int_tmpdir); free (g->int_cachedir); free (g->last_error); diff --git a/src/launch.c b/src/launch.c index ec061e3..e6972d1 100644 --- a/src/launch.c +++ b/src/launch.c @@ -425,9 +425,15 @@ int guestfs_int_create_socketname (guestfs_h *g, const char *filename, char (*sockpath)[UNIX_PATH_MAX]) { - char *path = g->tmpdir; + if (guestfs_int_lazy_make_sockdir (g) == -1) + return -1; + + if (strlen (g->sockdir) + 1 + strlen (filename) > UNIX_PATH_MAX-1) { + error (g, _("socket path too long: %s/%s"), g->sockdir, filename); + return -1; + } - snprintf (*sockpath, UNIX_PATH_MAX-1, "%s/%s", path, filename); + snprintf (*sockpath, UNIX_PATH_MAX-1, "%s/%s", g->sockdir, filename); (*sockpath)[UNIX_PATH_MAX-1] = '\0'; return 0; diff --git a/src/tmpdirs.c b/src/tmpdirs.c index 2ae9c74..e66ab9c 100644 --- a/src/tmpdirs.c +++ b/src/tmpdirs.c @@ -76,6 +76,12 @@ guestfs_int_set_env_tmpdir (guestfs_h *g, const char *tmpdir) } int +guestfs_int_set_env_runtimedir (guestfs_h *g, const char *runtimedir) +{ + return set_abs_path (g, runtimedir, &g->env_runtimedir); +} + +int guestfs_impl_set_tmpdir (guestfs_h *g, const char *tmpdir) { return set_abs_path (g, tmpdir, &g->int_tmpdir); @@ -119,6 +125,20 @@ guestfs_impl_get_cachedir (guestfs_h *g) return safe_strdup (g, str); } +/* Note this actually calculates the sockdir, so it never returns NULL. */ +char * +guestfs_impl_get_sockdir (guestfs_h *g) +{ + const char *str; + + if (g->env_runtimedir) + str = g->env_runtimedir; + else + str = "/tmp"; + + return safe_strdup (g, str); +} + static int lazy_make_tmpdir (guestfs_h *g, char *(*getdir) (guestfs_h *g), char **dest) { @@ -145,6 +165,12 @@ guestfs_int_lazy_make_tmpdir (guestfs_h *g) return lazy_make_tmpdir (g, guestfs_get_tmpdir, &g->tmpdir); } +int +guestfs_int_lazy_make_sockdir (guestfs_h *g) +{ + return lazy_make_tmpdir (g, guestfs_get_sockdir, &g->sockdir); +} + /* Recursively remove a temporary directory. If removal fails, just * return (it's a temporary directory so it'll eventually be cleaned * up by a temp cleaner). This is done using "rm -rf" because that's @@ -167,3 +193,10 @@ guestfs_int_remove_tmpdir (guestfs_h *g) if (g->tmpdir) guestfs_int_recursive_remove_dir (g, g->tmpdir); } + +void +guestfs_int_remove_sockdir (guestfs_h *g) +{ + if (g->sockdir) + guestfs_int_recursive_remove_dir (g, g->sockdir); +} diff --git a/test-tool/test-tool.c b/test-tool/test-tool.c index 9d23d6d..495316b 100644 --- a/test-tool/test-tool.c +++ b/test-tool/test-tool.c @@ -210,6 +210,9 @@ main (int argc, char *argv[]) p = getenv ("PATH"); if (p) printf ("PATH=%s\n", p); + p = getenv ("XDG_RUNTIME_DIR"); + if (p) + printf ("XDG_RUNTIME_DIR=%s\n", p); /* Print SELinux mode (don't worry if this fails, or if the command * doesn't even exist). @@ -255,6 +258,9 @@ main (int argc, char *argv[]) printf ("guestfs_get_recovery_proc: %d\n", guestfs_get_recovery_proc (g)); printf ("guestfs_get_selinux: %d\n", guestfs_get_selinux (g)); printf ("guestfs_get_smp: %d\n", guestfs_get_smp (g)); + p = guestfs_get_sockdir (g); + printf ("guestfs_get_sockdir: %s\n", p ? : "(null)"); + free (p); p = guestfs_get_tmpdir (g); printf ("guestfs_get_tmpdir: %s\n", p ? : "(null)"); free (p); -- 2.5.0 _______________________________________________ Libguestfs mailing list [email protected] https://www.redhat.com/mailman/listinfo/libguestfs
