+/* Skip leading and trailing whitespace, updating the original string
+ * in-place.
+ */
+void
+trim (char *str)
+{
+ size_t len = strlen (str);
+
+ while (len > 0 && c_isspace (str[len-1])) {
+ str[len-1] = '\0';
+ len--;
+ }
+
+ const char *p = str;
+ while (*p && c_isspace (*p)) {
+ p++;
+ len--;
+ }
+
+ memmove (str, p, len+1);
+}
+
+/* printf helper function so we can use %Q ("quoted") and %R to print
+ * shell-quoted strings. See guestfs(3)/EXTENDING LIBGUESTFS for more
+ * details.
+ */
+static int
+print_shell_quote (FILE *stream,
+ const struct printf_info *info ATTRIBUTE_UNUSED,
+ const void *const *args)
+{
+#define SAFE(c) (c_isalnum((c)) || \
+ (c) == '/' || (c) == '-' || (c) == '_' || (c) == '.')
+ int i, len;
+ const char *str = *((const char **) (args[0]));
+
+ for (i = len = 0; str[i]; ++i) {
+ if (!SAFE(str[i])) {
+ putc ('\\', stream);
+ len ++;
+ }
+ putc (str[i], stream);
+ len ++;
+ }
+
+ return len;
+}
+
+static int
+print_sysroot_shell_quote (FILE *stream,
+ const struct printf_info *info,
+ const void *const *args)
+{
+ fputs (sysroot, stream);
+ return sysroot_len + print_shell_quote (stream, info, args);
+}
+
+#ifdef HAVE_REGISTER_PRINTF_SPECIFIER
+static int
+print_arginfo (const struct printf_info *info ATTRIBUTE_UNUSED,
+ size_t n, int *argtypes, int *size)
+{
+ if (n > 0) {
+ argtypes[0] = PA_STRING;
+ size[0] = sizeof (const char *);
+ }
+ return 1;
+}
+#else
+#ifdef HAVE_REGISTER_PRINTF_FUNCTION
+static int
+print_arginfo (const struct printf_info *info, size_t n, int *argtypes)
+{
+ if (n > 0)
+ argtypes[0] = PA_STRING;
+ return 1;
+}
+#else
+#error "HAVE_REGISTER_PRINTF_{SPECIFIER|FUNCTION} not defined"
+#endif
+#endif
+
+/* Perform device name translation. Don't call this directly -
+ * use the RESOLVE_DEVICE macro.