1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
/* foundry-path.c
*
* Copyright 2024 Christian Hergert <chergert@redhat.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "config.h"
#include <errno.h>
#include <wordexp.h>
#include "foundry-path.h"
/**
* foundry_path_expand:
*
* This function will expand various "shell-like" features of the provided
* path using the POSIX wordexp(3) function. Command substitution will
* not be enabled, but path features such as ~user will be expanded.
*
* Returns: (transfer full): A newly allocated string containing the
* expansion. A copy of the input string upon failure to expand.
*/
char *
foundry_path_expand (const char *path)
{
wordexp_t state = { 0 };
char *replace_home = NULL;
char *ret = NULL;
char *escaped;
int r;
if (path == NULL)
return NULL;
/* Special case some path prefixes */
if (path[0] == '~')
{
if (path[1] == 0)
path = g_get_home_dir ();
else if (path[1] == G_DIR_SEPARATOR)
path = replace_home = g_strdup_printf ("%s%s", g_get_home_dir (), &path[1]);
}
else if (strncmp (path, "$HOME", 5) == 0)
{
if (path[5] == 0)
path = g_get_home_dir ();
else if (path[5] == G_DIR_SEPARATOR)
path = replace_home = g_strdup_printf ("%s%s", g_get_home_dir (), &path[5]);
}
escaped = g_shell_quote (path);
r = wordexp (escaped, &state, WRDE_NOCMD);
if (r == 0 && state.we_wordc > 0)
ret = g_strdup (state.we_wordv [0]);
wordfree (&state);
if (!g_path_is_absolute (ret))
{
g_autofree char *freeme = ret;
ret = g_build_filename (g_get_home_dir (), freeme, NULL);
}
g_free (replace_home);
g_free (escaped);
return ret;
}
/**
* foundry_path_collapse:
*
* This function will collapse a path that starts with the users home
* directory into a shorthand notation using ~/ for the home directory.
*
* If the path does not have the home directory as a prefix, it will
* simply return a copy of @path.
*
* Returns: (transfer full): A new path, possibly collapsed.
*/
char *
foundry_path_collapse (const char *path)
{
g_autofree char *expanded = NULL;
if (path == NULL)
return NULL;
expanded = foundry_path_expand (path);
if (g_str_has_prefix (expanded, g_get_home_dir ()))
return g_build_filename ("~",
expanded + strlen (g_get_home_dir ()),
NULL);
return g_steal_pointer (&expanded);
}
/**
* foundry_mkdir_with_parents:
* @path: a path to a directory to create
* @mode: the mode for the directory such as `0750`
*
* Similar to g_mkdir_with_parents() but runs on a dedicated thread.
*
* Returns: (transfer full): a [class@Dex.Future] that resolves to 0
* if successful, otherwise rejects with error.
*
* Deprecated: 1.1
*/
DexFuture *
foundry_mkdir_with_parents (const char *path,
int mode)
{
return dex_mkdir_with_parents (path, mode);
}
|