2011-10-15 14:56:47 +04:00
|
|
|
/*
|
|
|
|
Virtual File System path handlers
|
|
|
|
|
2024-01-01 09:46:17 +03:00
|
|
|
Copyright (C) 2011-2024
|
2014-02-12 10:33:10 +04:00
|
|
|
Free Software Foundation, Inc.
|
2011-04-14 16:21:30 +04:00
|
|
|
|
|
|
|
Written by:
|
2013-04-14 17:38:37 +04:00
|
|
|
Slava Zanko <slavazanko@gmail.com>, 2011, 2013
|
2022-05-07 11:02:24 +03:00
|
|
|
Andrew Borodin <aborodin@vmail.ru>, 2013-2022
|
2011-04-14 16:21:30 +04:00
|
|
|
|
|
|
|
This file is part of the Midnight Commander.
|
|
|
|
|
2011-10-15 14:56:47 +04:00
|
|
|
The Midnight Commander is free software: you can redistribute it
|
2011-04-14 16:21:30 +04:00
|
|
|
and/or modify it under the terms of the GNU General Public License as
|
2011-10-15 14:56:47 +04:00
|
|
|
published by the Free Software Foundation, either version 3 of the License,
|
|
|
|
or (at your option) any later version.
|
2011-04-14 16:21:30 +04:00
|
|
|
|
2011-10-15 14:56:47 +04:00
|
|
|
The Midnight Commander 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 General Public License for more details.
|
2011-04-14 16:21:30 +04:00
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
2011-10-15 14:56:47 +04:00
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2011-04-14 16:21:30 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \file
|
|
|
|
* \brief Source: Virtual File System: path handlers
|
|
|
|
* \author Slava Zanko
|
|
|
|
* \date 2011
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
2022-05-07 11:02:24 +03:00
|
|
|
#include <errno.h>
|
|
|
|
|
2011-04-14 16:21:30 +04:00
|
|
|
#include "lib/global.h"
|
2011-04-28 15:39:59 +04:00
|
|
|
#include "lib/strutil.h"
|
2011-11-09 01:10:51 +04:00
|
|
|
#include "lib/util.h" /* mc_build_filename() */
|
2011-06-07 13:22:31 +04:00
|
|
|
#include "lib/serialize.h"
|
2011-04-14 16:21:30 +04:00
|
|
|
|
2011-04-18 16:08:13 +04:00
|
|
|
#include "vfs.h"
|
|
|
|
#include "utilvfs.h"
|
2011-06-14 12:55:27 +04:00
|
|
|
#include "xdirentry.h"
|
2011-04-14 16:21:30 +04:00
|
|
|
#include "path.h"
|
|
|
|
|
2011-04-28 15:39:59 +04:00
|
|
|
extern GPtrArray *vfs__classes_list;
|
|
|
|
|
2011-04-14 16:21:30 +04:00
|
|
|
/*** global variables ****************************************************************************/
|
|
|
|
|
|
|
|
/*** file scope macro definitions ****************************************************************/
|
|
|
|
|
|
|
|
/*** file scope type declarations ****************************************************************/
|
|
|
|
|
Update template for .c files.
Add section for forward declarations of local functions. This section is
located before file scope variables because functions can be used in
strucutres (see find.c for example):
/*** forward declarations (file scope functions) *************************************************/
/* button callbacks */
static int start_stop (WButton * button, int action);
static int find_do_view_file (WButton * button, int action);
static int find_do_edit_file (WButton * button, int action);
/*** file scope variables ************************************************************************/
static struct
{
...
bcback_fn callback;
} fbuts[] =
{
...
{ B_STOP, NORMAL_BUTTON, N_("S&uspend"), 0, 0, NULL, start_stop },
...
{ B_VIEW, NORMAL_BUTTON, N_("&View - F3"), 0, 0, NULL, find_do_view_file },
{ B_VIEW, NORMAL_BUTTON, N_("&Edit - F4"), 0, 0, NULL, find_do_edit_file }
};
Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
2023-02-24 09:27:11 +03:00
|
|
|
/*** forward declarations (file scope functions) *************************************************/
|
|
|
|
|
2011-04-14 16:21:30 +04:00
|
|
|
/*** file scope variables ************************************************************************/
|
|
|
|
|
Update template for .c files.
Add section for forward declarations of local functions. This section is
located before file scope variables because functions can be used in
strucutres (see find.c for example):
/*** forward declarations (file scope functions) *************************************************/
/* button callbacks */
static int start_stop (WButton * button, int action);
static int find_do_view_file (WButton * button, int action);
static int find_do_edit_file (WButton * button, int action);
/*** file scope variables ************************************************************************/
static struct
{
...
bcback_fn callback;
} fbuts[] =
{
...
{ B_STOP, NORMAL_BUTTON, N_("S&uspend"), 0, 0, NULL, start_stop },
...
{ B_VIEW, NORMAL_BUTTON, N_("&View - F3"), 0, 0, NULL, find_do_view_file },
{ B_VIEW, NORMAL_BUTTON, N_("&Edit - F4"), 0, 0, NULL, find_do_edit_file }
};
Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
2023-02-24 09:27:11 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2011-04-14 16:21:30 +04:00
|
|
|
/*** file scope functions ************************************************************************/
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2011-04-28 15:39:59 +04:00
|
|
|
static gboolean
|
|
|
|
path_magic (const char *path)
|
|
|
|
{
|
|
|
|
struct stat buf;
|
|
|
|
|
|
|
|
return (stat (path, &buf) != 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Splits path extracting vfs part.
|
|
|
|
*
|
|
|
|
* Splits path
|
|
|
|
* \verbatim /p1#op/inpath \endverbatim
|
|
|
|
* into
|
|
|
|
* \verbatim inpath,op; \endverbatim
|
|
|
|
* returns which vfs it is.
|
|
|
|
* What is left in path is p1. You still want to g_free(path), you DON'T
|
|
|
|
* want to free neither *inpath nor *op
|
|
|
|
*/
|
|
|
|
|
|
|
|
static struct vfs_class *
|
|
|
|
_vfs_split_with_semi_skip_count (char *path, const char **inpath, const char **op,
|
|
|
|
size_t skip_count)
|
|
|
|
{
|
|
|
|
char *semi;
|
|
|
|
char *slash;
|
|
|
|
struct vfs_class *ret;
|
|
|
|
|
|
|
|
if (path == NULL)
|
|
|
|
vfs_die ("Cannot split NULL");
|
|
|
|
|
|
|
|
semi = strrstr_skip_count (path, "#", skip_count);
|
|
|
|
|
|
|
|
if ((semi == NULL) || (!path_magic (path)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
slash = strchr (semi, PATH_SEP);
|
|
|
|
*semi = '\0';
|
|
|
|
|
|
|
|
if (op != NULL)
|
|
|
|
*op = NULL;
|
|
|
|
|
|
|
|
if (inpath != NULL)
|
|
|
|
*inpath = NULL;
|
|
|
|
|
|
|
|
if (slash != NULL)
|
|
|
|
*slash = '\0';
|
|
|
|
|
|
|
|
ret = vfs_prefix_to_class (semi + 1);
|
|
|
|
if (ret != NULL)
|
|
|
|
{
|
|
|
|
if (op != NULL)
|
|
|
|
*op = semi + 1;
|
|
|
|
if (inpath != NULL)
|
|
|
|
*inpath = slash != NULL ? slash + 1 : NULL;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (slash != NULL)
|
|
|
|
*slash = PATH_SEP;
|
|
|
|
|
|
|
|
*semi = '#';
|
|
|
|
ret = _vfs_split_with_semi_skip_count (path, inpath, op, skip_count + 1);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-05-01 14:30:58 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* remove //, /./ and /../
|
|
|
|
*
|
|
|
|
* @return newly allocated string
|
|
|
|
*/
|
|
|
|
|
|
|
|
static char *
|
|
|
|
vfs_canon (const char *path)
|
|
|
|
{
|
2015-06-27 16:27:41 +03:00
|
|
|
char *result;
|
|
|
|
|
2012-03-12 11:48:41 +04:00
|
|
|
if (path == NULL)
|
2011-05-01 14:30:58 +04:00
|
|
|
vfs_die ("Cannot canonicalize NULL");
|
|
|
|
|
2015-01-07 11:34:53 +03:00
|
|
|
if (!IS_PATH_SEP (*path))
|
2011-05-01 14:30:58 +04:00
|
|
|
{
|
2015-06-27 16:27:41 +03:00
|
|
|
/* Relative to current directory */
|
|
|
|
|
|
|
|
char *local;
|
2012-03-12 11:48:41 +04:00
|
|
|
|
2024-05-05 10:04:38 +03:00
|
|
|
#ifdef HAVE_CHARSET
|
2012-08-28 14:20:30 +04:00
|
|
|
if (g_str_has_prefix (path, VFS_ENCODING_PREFIX))
|
2012-03-12 11:48:41 +04:00
|
|
|
{
|
2012-08-28 14:20:30 +04:00
|
|
|
/*
|
|
|
|
encoding prefix placed at start of string without the leading slash
|
|
|
|
should be autofixed by adding the leading slash
|
|
|
|
*/
|
2016-03-25 21:33:44 +03:00
|
|
|
local = mc_build_filename (PATH_SEP_STR, path, (char *) NULL);
|
2012-03-12 11:48:41 +04:00
|
|
|
}
|
2012-08-28 14:20:30 +04:00
|
|
|
else
|
2024-05-05 10:04:38 +03:00
|
|
|
#endif
|
2012-08-28 14:20:30 +04:00
|
|
|
{
|
2015-10-18 08:07:08 +03:00
|
|
|
const char *curr_dir;
|
2012-09-01 13:06:20 +04:00
|
|
|
|
|
|
|
curr_dir = vfs_get_current_dir ();
|
2016-03-25 21:33:44 +03:00
|
|
|
local = mc_build_filename (curr_dir, path, (char *) NULL);
|
2012-08-28 14:20:30 +04:00
|
|
|
}
|
2011-05-01 14:30:58 +04:00
|
|
|
result = vfs_canon (local);
|
|
|
|
g_free (local);
|
|
|
|
}
|
2015-06-27 16:27:41 +03:00
|
|
|
else
|
2011-05-01 14:30:58 +04:00
|
|
|
{
|
2015-06-27 16:27:41 +03:00
|
|
|
/* Absolute path */
|
2012-03-12 11:48:41 +04:00
|
|
|
|
|
|
|
result = g_strdup (path);
|
2011-05-01 14:30:58 +04:00
|
|
|
canonicalize_pathname (result);
|
|
|
|
}
|
2015-06-27 16:27:41 +03:00
|
|
|
|
|
|
|
return result;
|
2011-05-01 14:30:58 +04:00
|
|
|
}
|
|
|
|
|
2011-06-13 14:19:47 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/** Extract the hostname and username from the path
|
|
|
|
*
|
|
|
|
* Format of the path is [user@]hostname:port/remote-dir, e.g.:
|
|
|
|
*
|
|
|
|
* ftp://sunsite.unc.edu/pub/linux
|
|
|
|
* ftp://miguel@sphinx.nuclecu.unam.mx/c/nc
|
|
|
|
* ftp://tsx-11.mit.edu:8192/
|
|
|
|
* ftp://joe@foo.edu:11321/private
|
|
|
|
* ftp://joe:password@foo.se
|
|
|
|
*
|
|
|
|
* @param path_element is an input string to be parsed
|
|
|
|
* @param path is an input string to be parsed
|
|
|
|
*
|
|
|
|
* @return g_malloc()ed url info.
|
|
|
|
* If the user is empty, e.g. ftp://@roxanne/private, and URL_USE_ANONYMOUS
|
|
|
|
* is not set, then the current login name is supplied.
|
|
|
|
* Return value is a g_malloc()ed structure with the pathname relative to the
|
|
|
|
* host.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_url_split (vfs_path_element_t *path_element, const char *path)
|
2011-06-13 14:19:47 +04:00
|
|
|
{
|
|
|
|
char *pcopy;
|
2013-10-15 10:34:04 +04:00
|
|
|
char *colon, *at, *rest;
|
2011-06-13 14:19:47 +04:00
|
|
|
|
|
|
|
path_element->port = 0;
|
|
|
|
|
|
|
|
pcopy = g_strdup (path);
|
|
|
|
|
|
|
|
/* search for any possible user */
|
|
|
|
at = strrchr (pcopy, '@');
|
|
|
|
|
|
|
|
/* We have a username */
|
|
|
|
if (at == NULL)
|
|
|
|
rest = pcopy;
|
|
|
|
else
|
|
|
|
{
|
2017-12-16 21:11:38 +03:00
|
|
|
const char *pend;
|
2013-10-15 10:34:04 +04:00
|
|
|
char *inner_colon;
|
|
|
|
|
2017-12-16 21:11:38 +03:00
|
|
|
pend = strchr (at, '\0');
|
2011-06-13 14:19:47 +04:00
|
|
|
*at = '\0';
|
2017-12-16 21:11:38 +03:00
|
|
|
|
2011-06-13 14:19:47 +04:00
|
|
|
inner_colon = strchr (pcopy, ':');
|
|
|
|
if (inner_colon != NULL)
|
|
|
|
{
|
|
|
|
*inner_colon = '\0';
|
|
|
|
inner_colon++;
|
|
|
|
path_element->password = g_strdup (inner_colon);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*pcopy != '\0')
|
|
|
|
path_element->user = g_strdup (pcopy);
|
|
|
|
|
|
|
|
if (pend == at + 1)
|
|
|
|
rest = at;
|
|
|
|
else
|
|
|
|
rest = at + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if the host comes with a port spec, if so, chop it */
|
|
|
|
if (*rest != '[')
|
|
|
|
colon = strchr (rest, ':');
|
|
|
|
else
|
|
|
|
{
|
|
|
|
colon = strchr (++rest, ']');
|
|
|
|
if (colon != NULL)
|
|
|
|
{
|
2017-12-16 21:11:38 +03:00
|
|
|
*colon = '\0';
|
2011-06-13 14:19:47 +04:00
|
|
|
colon++;
|
2017-12-16 21:11:38 +03:00
|
|
|
*colon = '\0';
|
2011-07-05 17:05:15 +04:00
|
|
|
path_element->ipv6 = TRUE;
|
2011-06-13 14:19:47 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (colon != NULL)
|
|
|
|
{
|
|
|
|
*colon = '\0';
|
2013-10-10 16:21:26 +04:00
|
|
|
/* cppcheck-suppress invalidscanf */
|
2011-06-13 14:19:47 +04:00
|
|
|
if (sscanf (colon + 1, "%d", &path_element->port) == 1)
|
|
|
|
{
|
|
|
|
if (path_element->port <= 0 || path_element->port >= 65536)
|
|
|
|
path_element->port = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
while (*(++colon) != '\0')
|
|
|
|
{
|
|
|
|
switch (*colon)
|
|
|
|
{
|
|
|
|
case 'C':
|
|
|
|
path_element->port = 1;
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
path_element->port = 2;
|
|
|
|
break;
|
2015-04-19 13:57:38 +03:00
|
|
|
default:
|
|
|
|
break;
|
2011-06-13 14:19:47 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
path_element->host = g_strdup (rest);
|
|
|
|
g_free (pcopy);
|
|
|
|
}
|
|
|
|
|
2011-06-07 13:22:31 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* get VFS class for the given name
|
|
|
|
*
|
|
|
|
* @param class_name name of class
|
|
|
|
*
|
|
|
|
* @return pointer to class structure or NULL if class not found
|
|
|
|
*/
|
|
|
|
|
|
|
|
static struct vfs_class *
|
|
|
|
vfs_get_class_by_name (const char *class_name)
|
|
|
|
{
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
if (class_name == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (i = 0; i < vfs__classes_list->len; i++)
|
|
|
|
{
|
2018-09-12 14:01:28 +03:00
|
|
|
struct vfs_class *vfs = VFS_CLASS (g_ptr_array_index (vfs__classes_list, i));
|
2011-06-07 13:22:31 +04:00
|
|
|
if ((vfs->name != NULL) && (strcmp (vfs->name, class_name) == 0))
|
|
|
|
return vfs;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2011-06-14 12:55:27 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* Check if path string contain URL-like elements
|
|
|
|
*
|
|
|
|
* @param path_str path
|
|
|
|
*
|
|
|
|
* @return TRUE if path is deprecated or FALSE otherwise
|
|
|
|
*/
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
vfs_path_is_str_path_deprecated (const char *path_str)
|
|
|
|
{
|
2011-06-14 16:09:59 +04:00
|
|
|
return strstr (path_str, VFS_PATH_URL_DELIMITER) == NULL;
|
2011-06-14 12:55:27 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/** Split path string to path elements by deprecated algorithm.
|
|
|
|
*
|
|
|
|
* @param path_str VFS-path
|
|
|
|
*
|
|
|
|
* @return pointer to newly created vfs_path_t object with filled path elements array.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static vfs_path_t *
|
2017-06-09 10:14:46 +03:00
|
|
|
vfs_path_from_str_deprecated_parser (char *path)
|
2011-06-14 12:55:27 +04:00
|
|
|
{
|
|
|
|
vfs_path_t *vpath;
|
|
|
|
vfs_path_element_t *element;
|
|
|
|
struct vfs_class *class;
|
|
|
|
const char *local, *op;
|
|
|
|
|
2023-04-02 15:46:26 +03:00
|
|
|
vpath = vfs_path_new (FALSE);
|
2011-06-14 12:55:27 +04:00
|
|
|
|
|
|
|
while ((class = _vfs_split_with_semi_skip_count (path, &local, &op, 0)) != NULL)
|
|
|
|
{
|
|
|
|
char *url_params;
|
|
|
|
element = g_new0 (vfs_path_element_t, 1);
|
|
|
|
element->class = class;
|
|
|
|
if (local == NULL)
|
|
|
|
local = "";
|
|
|
|
element->path = vfs_translate_path_n (local);
|
|
|
|
|
2012-04-30 14:58:25 +04:00
|
|
|
#ifdef HAVE_CHARSET
|
2013-04-24 14:47:44 +04:00
|
|
|
element->encoding = vfs_get_encoding (local, -1);
|
2011-08-15 15:37:59 +04:00
|
|
|
element->dir.converter =
|
|
|
|
(element->encoding != NULL) ? str_crt_conv_from (element->encoding) : INVALID_CONV;
|
2012-04-30 14:58:25 +04:00
|
|
|
#endif
|
2011-06-14 12:55:27 +04:00
|
|
|
|
|
|
|
url_params = strchr (op, ':'); /* skip VFS prefix */
|
|
|
|
if (url_params != NULL)
|
|
|
|
{
|
|
|
|
*url_params = '\0';
|
|
|
|
url_params++;
|
|
|
|
vfs_path_url_split (element, url_params);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*op != '\0')
|
|
|
|
element->vfs_prefix = g_strdup (op);
|
|
|
|
|
2011-09-29 13:02:23 +04:00
|
|
|
g_array_prepend_val (vpath->path, element);
|
2011-06-14 12:55:27 +04:00
|
|
|
}
|
|
|
|
if (path[0] != '\0')
|
|
|
|
{
|
|
|
|
element = g_new0 (vfs_path_element_t, 1);
|
|
|
|
element->class = g_ptr_array_index (vfs__classes_list, 0);
|
|
|
|
element->path = vfs_translate_path_n (path);
|
|
|
|
|
2012-04-30 14:58:25 +04:00
|
|
|
#ifdef HAVE_CHARSET
|
2013-04-24 14:47:44 +04:00
|
|
|
element->encoding = vfs_get_encoding (path, -1);
|
2011-08-15 15:37:59 +04:00
|
|
|
element->dir.converter =
|
|
|
|
(element->encoding != NULL) ? str_crt_conv_from (element->encoding) : INVALID_CONV;
|
2012-04-30 14:58:25 +04:00
|
|
|
#endif
|
2011-09-29 13:02:23 +04:00
|
|
|
g_array_prepend_val (vpath->path, element);
|
2011-06-14 12:55:27 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return vpath;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/** Split path string to path elements by URL algorithm.
|
|
|
|
*
|
|
|
|
* @param path_str VFS-path
|
2012-08-28 14:20:30 +04:00
|
|
|
* @param flags flags for converter
|
2011-06-14 12:55:27 +04:00
|
|
|
*
|
|
|
|
* @return pointer to newly created vfs_path_t object with filled path elements array.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static vfs_path_t *
|
2017-06-09 10:14:46 +03:00
|
|
|
vfs_path_from_str_uri_parser (char *path)
|
2011-06-14 12:55:27 +04:00
|
|
|
{
|
2024-05-04 14:59:09 +03:00
|
|
|
gboolean path_is_absolute;
|
2011-06-14 12:55:27 +04:00
|
|
|
vfs_path_t *vpath;
|
|
|
|
vfs_path_element_t *element;
|
|
|
|
char *url_delimiter;
|
|
|
|
|
2024-05-04 14:59:09 +03:00
|
|
|
if (path == NULL)
|
|
|
|
return vfs_path_new (FALSE);
|
|
|
|
|
|
|
|
path_is_absolute = IS_PATH_SEP (*path);
|
|
|
|
#ifdef HAVE_CHARSET
|
|
|
|
path_is_absolute = path_is_absolute || g_str_has_prefix (path, VFS_ENCODING_PREFIX);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
vpath = vfs_path_new (!path_is_absolute);
|
2011-06-14 12:55:27 +04:00
|
|
|
|
2011-06-14 16:09:59 +04:00
|
|
|
while ((url_delimiter = g_strrstr (path, VFS_PATH_URL_DELIMITER)) != NULL)
|
2011-06-14 12:55:27 +04:00
|
|
|
{
|
|
|
|
char *vfs_prefix_start;
|
|
|
|
char *real_vfs_prefix_start = url_delimiter;
|
|
|
|
|
2015-01-07 11:34:53 +03:00
|
|
|
while (real_vfs_prefix_start > path && !IS_PATH_SEP (*real_vfs_prefix_start))
|
2011-06-14 12:55:27 +04:00
|
|
|
real_vfs_prefix_start--;
|
|
|
|
vfs_prefix_start = real_vfs_prefix_start;
|
|
|
|
|
2015-01-07 11:34:53 +03:00
|
|
|
if (IS_PATH_SEP (*vfs_prefix_start))
|
2024-05-21 21:44:08 +03:00
|
|
|
vfs_prefix_start++;
|
2011-06-14 16:09:59 +04:00
|
|
|
|
|
|
|
*url_delimiter = '\0';
|
2011-06-14 12:55:27 +04:00
|
|
|
|
|
|
|
element = g_new0 (vfs_path_element_t, 1);
|
|
|
|
element->class = vfs_prefix_to_class (vfs_prefix_start);
|
|
|
|
element->vfs_prefix = g_strdup (vfs_prefix_start);
|
|
|
|
|
2011-06-14 16:09:59 +04:00
|
|
|
url_delimiter += strlen (VFS_PATH_URL_DELIMITER);
|
2019-05-09 15:21:09 +03:00
|
|
|
|
2019-11-18 21:24:13 +03:00
|
|
|
if (element->class != NULL && (element->class->flags & VFSF_REMOTE) != 0)
|
2011-06-14 12:55:27 +04:00
|
|
|
{
|
2013-10-15 10:34:04 +04:00
|
|
|
char *slash_pointer;
|
|
|
|
|
2011-06-14 12:55:27 +04:00
|
|
|
slash_pointer = strchr (url_delimiter, PATH_SEP);
|
|
|
|
if (slash_pointer == NULL)
|
|
|
|
element->path = g_strdup ("");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
element->path = vfs_translate_path_n (slash_pointer + 1);
|
2012-04-30 14:58:25 +04:00
|
|
|
#ifdef HAVE_CHARSET
|
2013-04-24 14:47:44 +04:00
|
|
|
element->encoding = vfs_get_encoding (slash_pointer, -1);
|
2012-04-30 14:58:25 +04:00
|
|
|
#endif
|
2011-06-14 12:55:27 +04:00
|
|
|
*slash_pointer = '\0';
|
|
|
|
}
|
|
|
|
vfs_path_url_split (element, url_delimiter);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
element->path = vfs_translate_path_n (url_delimiter);
|
2012-04-30 14:58:25 +04:00
|
|
|
#ifdef HAVE_CHARSET
|
2013-04-24 14:47:44 +04:00
|
|
|
element->encoding = vfs_get_encoding (url_delimiter, -1);
|
2012-04-30 14:58:25 +04:00
|
|
|
#endif
|
2011-06-14 12:55:27 +04:00
|
|
|
}
|
2012-04-30 14:58:25 +04:00
|
|
|
#ifdef HAVE_CHARSET
|
2011-08-15 15:37:59 +04:00
|
|
|
element->dir.converter =
|
|
|
|
(element->encoding != NULL) ? str_crt_conv_from (element->encoding) : INVALID_CONV;
|
2012-04-30 14:58:25 +04:00
|
|
|
#endif
|
2011-09-29 13:02:23 +04:00
|
|
|
g_array_prepend_val (vpath->path, element);
|
2011-06-14 12:55:27 +04:00
|
|
|
|
2015-01-07 11:34:53 +03:00
|
|
|
if ((real_vfs_prefix_start > path && IS_PATH_SEP (*real_vfs_prefix_start)) ||
|
|
|
|
(real_vfs_prefix_start == path && !IS_PATH_SEP (*real_vfs_prefix_start)))
|
2011-06-14 12:55:27 +04:00
|
|
|
*real_vfs_prefix_start = '\0';
|
|
|
|
else
|
|
|
|
*(real_vfs_prefix_start + 1) = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (path[0] != '\0')
|
|
|
|
{
|
|
|
|
element = g_new0 (vfs_path_element_t, 1);
|
|
|
|
element->class = g_ptr_array_index (vfs__classes_list, 0);
|
|
|
|
element->path = vfs_translate_path_n (path);
|
2012-04-30 14:58:25 +04:00
|
|
|
#ifdef HAVE_CHARSET
|
2013-04-24 14:47:44 +04:00
|
|
|
element->encoding = vfs_get_encoding (path, -1);
|
2011-08-15 15:37:59 +04:00
|
|
|
element->dir.converter =
|
|
|
|
(element->encoding != NULL) ? str_crt_conv_from (element->encoding) : INVALID_CONV;
|
2012-04-30 14:58:25 +04:00
|
|
|
#endif
|
2011-09-29 13:02:23 +04:00
|
|
|
g_array_prepend_val (vpath->path, element);
|
2011-06-14 12:55:27 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return vpath;
|
|
|
|
}
|
|
|
|
|
2011-08-01 00:44:15 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* Add element's class info to result string (such as VFS name, host, encoding etc)
|
|
|
|
* This function used as helper only in vfs_path_tokens_get() function
|
|
|
|
*
|
|
|
|
* @param element current path element
|
|
|
|
* @param ret_tokens total tikens for return
|
|
|
|
* @param element_tokens accumulated element-only tokens
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_tokens_add_class_info (const vfs_path_element_t *element, GString *ret_tokens,
|
|
|
|
GString *element_tokens)
|
2011-08-01 00:44:15 +04:00
|
|
|
{
|
2019-11-18 21:24:13 +03:00
|
|
|
if (((element->class->flags & VFSF_LOCAL) == 0 || ret_tokens->len > 0)
|
2011-08-01 00:44:15 +04:00
|
|
|
&& element_tokens->len > 0)
|
|
|
|
{
|
2022-10-30 09:28:25 +03:00
|
|
|
GString *url_str;
|
2011-08-01 00:44:15 +04:00
|
|
|
|
2015-01-07 11:34:53 +03:00
|
|
|
if (ret_tokens->len > 0 && !IS_PATH_SEP (ret_tokens->str[ret_tokens->len - 1]))
|
2011-08-01 00:44:15 +04:00
|
|
|
g_string_append_c (ret_tokens, PATH_SEP);
|
|
|
|
|
|
|
|
g_string_append (ret_tokens, element->vfs_prefix);
|
|
|
|
g_string_append (ret_tokens, VFS_PATH_URL_DELIMITER);
|
|
|
|
|
2011-09-28 00:31:20 +04:00
|
|
|
url_str = vfs_path_build_url_params_str (element, TRUE);
|
2023-08-27 12:39:04 +03:00
|
|
|
if (url_str != NULL)
|
2011-08-01 00:44:15 +04:00
|
|
|
{
|
2022-10-30 09:28:25 +03:00
|
|
|
g_string_append_len (ret_tokens, url_str->str, url_str->len);
|
2011-08-01 00:44:15 +04:00
|
|
|
g_string_append_c (ret_tokens, PATH_SEP);
|
2023-08-27 12:39:04 +03:00
|
|
|
g_string_free (url_str, TRUE);
|
2011-08-01 00:44:15 +04:00
|
|
|
}
|
|
|
|
}
|
2012-04-30 14:58:25 +04:00
|
|
|
|
|
|
|
#ifdef HAVE_CHARSET
|
2011-08-01 00:44:15 +04:00
|
|
|
if (element->encoding != NULL)
|
|
|
|
{
|
2015-01-07 11:34:53 +03:00
|
|
|
if (ret_tokens->len > 0 && !IS_PATH_SEP (ret_tokens->str[ret_tokens->len - 1]))
|
2011-08-01 00:44:15 +04:00
|
|
|
g_string_append (ret_tokens, PATH_SEP_STR);
|
|
|
|
g_string_append (ret_tokens, VFS_ENCODING_PREFIX);
|
|
|
|
g_string_append (ret_tokens, element->encoding);
|
|
|
|
g_string_append (ret_tokens, PATH_SEP_STR);
|
|
|
|
}
|
2012-04-30 14:58:25 +04:00
|
|
|
#endif
|
2011-08-01 00:44:15 +04:00
|
|
|
|
|
|
|
g_string_append (ret_tokens, element_tokens->str);
|
|
|
|
}
|
|
|
|
|
2011-11-27 00:12:52 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* Strip path to home dir.
|
|
|
|
* @param dir pointer to string contains full path
|
|
|
|
*/
|
|
|
|
|
|
|
|
static char *
|
|
|
|
vfs_path_strip_home (const char *dir)
|
|
|
|
{
|
|
|
|
const char *home_dir = mc_config_get_home_dir ();
|
|
|
|
|
|
|
|
if (home_dir != NULL)
|
|
|
|
{
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
len = strlen (home_dir);
|
|
|
|
|
2015-01-07 11:34:53 +03:00
|
|
|
if (strncmp (dir, home_dir, len) == 0 && (IS_PATH_SEP (dir[len]) || dir[len] == '\0'))
|
2011-11-27 00:12:52 +04:00
|
|
|
return g_strdup_printf ("~%s", dir + len);
|
|
|
|
}
|
|
|
|
|
|
|
|
return g_strdup (dir);
|
|
|
|
}
|
|
|
|
|
2011-04-14 16:21:30 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/*** public functions ****************************************************************************/
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2012-02-07 15:54:58 +04:00
|
|
|
#define vfs_append_from_path(appendfrom, is_relative) \
|
2011-08-15 15:37:59 +04:00
|
|
|
{ \
|
2019-11-18 21:24:13 +03:00
|
|
|
if ((flags & VPF_STRIP_HOME) && element_index == 0 && \
|
|
|
|
(element->class->flags & VFSF_LOCAL) != 0) \
|
2011-11-27 00:12:52 +04:00
|
|
|
{ \
|
|
|
|
char *stripped_home_str; \
|
|
|
|
stripped_home_str = vfs_path_strip_home (appendfrom); \
|
|
|
|
g_string_append (buffer, stripped_home_str); \
|
|
|
|
g_free (stripped_home_str); \
|
|
|
|
} \
|
|
|
|
else \
|
|
|
|
{ \
|
2015-01-07 11:34:53 +03:00
|
|
|
if (!is_relative && !IS_PATH_SEP (*appendfrom) && *appendfrom != '\0' \
|
|
|
|
&& (buffer->len == 0 || !IS_PATH_SEP (buffer->str[buffer->len - 1]))) \
|
2011-11-27 00:12:52 +04:00
|
|
|
g_string_append_c (buffer, PATH_SEP); \
|
|
|
|
g_string_append (buffer, appendfrom); \
|
|
|
|
} \
|
2011-08-15 15:37:59 +04:00
|
|
|
}
|
|
|
|
|
2012-08-31 18:05:29 +04:00
|
|
|
/**
|
|
|
|
* Convert first elements_count elements from vfs_path_t to string representation with flags.
|
|
|
|
*
|
|
|
|
* @param vpath pointer to vfs_path_t object
|
|
|
|
* @param elements_count count of first elements for convert
|
|
|
|
* @param flags for converter
|
|
|
|
*
|
|
|
|
* @return pointer to newly created string.
|
|
|
|
*/
|
|
|
|
|
2011-04-14 16:21:30 +04:00
|
|
|
char *
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_to_str_flags (const vfs_path_t *vpath, int elements_count, vfs_path_flag_t flags)
|
2011-04-14 16:21:30 +04:00
|
|
|
{
|
2011-04-28 15:39:59 +04:00
|
|
|
int element_index;
|
2011-04-14 16:21:30 +04:00
|
|
|
GString *buffer;
|
2023-04-09 21:01:46 +03:00
|
|
|
#ifdef HAVE_CHARSET
|
|
|
|
GString *recode_buffer = NULL;
|
|
|
|
#endif
|
2011-04-14 16:21:30 +04:00
|
|
|
|
2011-04-28 15:39:59 +04:00
|
|
|
if (vpath == NULL)
|
2011-04-14 16:21:30 +04:00
|
|
|
return NULL;
|
|
|
|
|
2011-11-27 00:12:52 +04:00
|
|
|
if (elements_count == 0 || elements_count > vfs_path_elements_count (vpath))
|
2011-04-28 15:39:59 +04:00
|
|
|
elements_count = vfs_path_elements_count (vpath);
|
|
|
|
|
|
|
|
if (elements_count < 0)
|
|
|
|
elements_count = vfs_path_elements_count (vpath) + elements_count;
|
|
|
|
|
2011-04-14 16:21:30 +04:00
|
|
|
buffer = g_string_new ("");
|
|
|
|
|
2011-04-28 15:39:59 +04:00
|
|
|
for (element_index = 0; element_index < elements_count; element_index++)
|
2011-04-14 16:21:30 +04:00
|
|
|
{
|
2012-01-03 13:35:57 +04:00
|
|
|
const vfs_path_element_t *element;
|
2012-02-07 15:54:58 +04:00
|
|
|
gboolean is_relative = vpath->relative && (element_index == 0);
|
2012-01-03 13:35:57 +04:00
|
|
|
|
|
|
|
element = vfs_path_get_by_index (vpath, element_index);
|
2011-06-14 12:28:51 +04:00
|
|
|
if (element->vfs_prefix != NULL)
|
2011-04-28 15:39:59 +04:00
|
|
|
{
|
2022-10-30 09:28:25 +03:00
|
|
|
GString *url_str;
|
|
|
|
|
2015-01-07 11:34:53 +03:00
|
|
|
if (!is_relative && (buffer->len == 0 || !IS_PATH_SEP (buffer->str[buffer->len - 1])))
|
2011-08-01 00:44:15 +04:00
|
|
|
g_string_append_c (buffer, PATH_SEP);
|
2011-06-14 16:09:59 +04:00
|
|
|
|
2011-06-14 12:28:51 +04:00
|
|
|
g_string_append (buffer, element->vfs_prefix);
|
2011-06-14 16:09:59 +04:00
|
|
|
g_string_append (buffer, VFS_PATH_URL_DELIMITER);
|
2011-06-14 12:28:51 +04:00
|
|
|
|
2024-05-21 21:44:08 +03:00
|
|
|
url_str = vfs_path_build_url_params_str (element, (flags & VPF_STRIP_PASSWORD) == 0);
|
2023-08-27 12:39:04 +03:00
|
|
|
if (url_str != NULL)
|
2012-03-22 16:26:52 +04:00
|
|
|
{
|
2022-10-30 09:28:25 +03:00
|
|
|
g_string_append_len (buffer, url_str->str, url_str->len);
|
2012-03-22 16:26:52 +04:00
|
|
|
g_string_append_c (buffer, PATH_SEP);
|
2023-08-27 12:39:04 +03:00
|
|
|
g_string_free (url_str, TRUE);
|
2012-03-22 16:26:52 +04:00
|
|
|
}
|
2011-04-28 15:39:59 +04:00
|
|
|
}
|
2011-06-14 12:28:51 +04:00
|
|
|
|
2012-04-30 14:58:25 +04:00
|
|
|
#ifdef HAVE_CHARSET
|
2011-11-27 00:12:52 +04:00
|
|
|
if ((flags & VPF_RECODE) == 0 && vfs_path_element_need_cleanup_converter (element))
|
2011-05-30 17:54:45 +04:00
|
|
|
{
|
2011-11-27 04:09:41 +04:00
|
|
|
if ((flags & VPF_HIDE_CHARSET) == 0)
|
|
|
|
{
|
2012-02-07 15:54:58 +04:00
|
|
|
if ((!is_relative)
|
2015-01-07 11:34:53 +03:00
|
|
|
&& (buffer->len == 0 || !IS_PATH_SEP (buffer->str[buffer->len - 1])))
|
2011-11-27 04:09:41 +04:00
|
|
|
g_string_append (buffer, PATH_SEP_STR);
|
|
|
|
g_string_append (buffer, VFS_ENCODING_PREFIX);
|
|
|
|
g_string_append (buffer, element->encoding);
|
|
|
|
}
|
2023-04-09 21:01:46 +03:00
|
|
|
|
|
|
|
if (recode_buffer == NULL)
|
|
|
|
recode_buffer = g_string_sized_new (32);
|
|
|
|
else
|
|
|
|
g_string_set_size (recode_buffer, 0);
|
|
|
|
|
2011-08-15 15:37:59 +04:00
|
|
|
str_vfs_convert_from (element->dir.converter, element->path, recode_buffer);
|
2012-02-07 15:54:58 +04:00
|
|
|
vfs_append_from_path (recode_buffer->str, is_relative);
|
2011-08-15 15:37:59 +04:00
|
|
|
}
|
|
|
|
else
|
2012-04-30 14:58:25 +04:00
|
|
|
#endif
|
2011-08-15 15:37:59 +04:00
|
|
|
{
|
2012-02-07 15:54:58 +04:00
|
|
|
vfs_append_from_path (element->path, is_relative);
|
2011-05-30 17:54:45 +04:00
|
|
|
}
|
2011-04-14 16:21:30 +04:00
|
|
|
}
|
2023-04-09 21:01:46 +03:00
|
|
|
|
|
|
|
#ifdef HAVE_CHARSET
|
|
|
|
if (recode_buffer != NULL)
|
|
|
|
g_string_free (recode_buffer, TRUE);
|
|
|
|
#endif
|
|
|
|
|
2011-04-18 16:08:13 +04:00
|
|
|
return g_string_free (buffer, FALSE);
|
2011-04-14 16:21:30 +04:00
|
|
|
}
|
|
|
|
|
2011-08-15 15:37:59 +04:00
|
|
|
#undef vfs_append_from_path
|
|
|
|
|
2011-11-27 00:12:52 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* Convert first elements_count elements from vfs_path_t to string representation.
|
|
|
|
*
|
|
|
|
* @param vpath pointer to vfs_path_t object
|
|
|
|
* @param elements_count count of first elements for convert
|
|
|
|
*
|
|
|
|
* @return pointer to newly created string.
|
|
|
|
*/
|
|
|
|
|
|
|
|
char *
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_to_str_elements_count (const vfs_path_t *vpath, int elements_count)
|
2011-11-27 00:12:52 +04:00
|
|
|
{
|
|
|
|
return vfs_path_to_str_flags (vpath, elements_count, VPF_NONE);
|
|
|
|
}
|
|
|
|
|
2011-04-28 15:39:59 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
2011-06-29 14:12:19 +04:00
|
|
|
* Split path string to path elements with flags for change parce process.
|
2011-04-28 15:39:59 +04:00
|
|
|
*
|
|
|
|
* @param path_str VFS-path
|
2011-06-29 14:12:19 +04:00
|
|
|
* @param flags flags for parser
|
2011-04-28 15:39:59 +04:00
|
|
|
*
|
2011-05-01 14:30:58 +04:00
|
|
|
* @return pointer to newly created vfs_path_t object with filled path elements array.
|
2011-04-28 15:39:59 +04:00
|
|
|
*/
|
2011-04-14 16:21:30 +04:00
|
|
|
|
|
|
|
vfs_path_t *
|
2011-06-29 14:12:19 +04:00
|
|
|
vfs_path_from_str_flags (const char *path_str, vfs_path_flag_t flags)
|
2011-04-14 16:21:30 +04:00
|
|
|
{
|
2011-04-28 15:39:59 +04:00
|
|
|
vfs_path_t *vpath;
|
|
|
|
char *path;
|
2011-04-14 16:21:30 +04:00
|
|
|
|
|
|
|
if (path_str == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2011-06-29 14:12:19 +04:00
|
|
|
if ((flags & VPF_NO_CANON) == 0)
|
|
|
|
path = vfs_canon (path_str);
|
|
|
|
else
|
|
|
|
path = g_strdup (path_str);
|
|
|
|
|
2011-06-01 15:53:08 +04:00
|
|
|
if (path == NULL)
|
2011-04-20 16:59:06 +04:00
|
|
|
return NULL;
|
2011-05-30 11:16:40 +04:00
|
|
|
|
2011-06-29 14:41:14 +04:00
|
|
|
if ((flags & VPF_USE_DEPRECATED_PARSER) != 0 && vfs_path_is_str_path_deprecated (path))
|
2017-06-09 10:14:46 +03:00
|
|
|
vpath = vfs_path_from_str_deprecated_parser (path);
|
2011-06-14 12:55:27 +04:00
|
|
|
else
|
2017-06-09 10:14:46 +03:00
|
|
|
vpath = vfs_path_from_str_uri_parser (path);
|
2011-06-01 14:56:52 +04:00
|
|
|
|
2013-11-08 17:57:42 +04:00
|
|
|
vpath->str = vfs_path_to_str_flags (vpath, 0, flags);
|
2011-04-28 15:39:59 +04:00
|
|
|
g_free (path);
|
2011-04-14 16:21:30 +04:00
|
|
|
|
2011-04-28 15:39:59 +04:00
|
|
|
return vpath;
|
2011-04-14 16:21:30 +04:00
|
|
|
}
|
|
|
|
|
2011-06-29 14:12:19 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* Split path string to path elements.
|
|
|
|
*
|
|
|
|
* @param path_str VFS-path
|
|
|
|
*
|
|
|
|
* @return pointer to newly created vfs_path_t object with filled path elements array.
|
|
|
|
*/
|
|
|
|
|
|
|
|
vfs_path_t *
|
|
|
|
vfs_path_from_str (const char *path_str)
|
|
|
|
{
|
|
|
|
return vfs_path_from_str_flags (path_str, VPF_NONE);
|
|
|
|
}
|
|
|
|
|
2011-04-14 16:21:30 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2011-04-28 15:39:59 +04:00
|
|
|
/*
|
|
|
|
* Create new vfs_path_t object.
|
|
|
|
*
|
|
|
|
* @return pointer to newly created vfs_path_t object.
|
|
|
|
*/
|
2011-04-14 16:21:30 +04:00
|
|
|
|
|
|
|
vfs_path_t *
|
2023-04-02 15:46:26 +03:00
|
|
|
vfs_path_new (gboolean relative)
|
2011-04-14 16:21:30 +04:00
|
|
|
{
|
2011-04-26 17:29:34 +04:00
|
|
|
vfs_path_t *vpath;
|
2011-09-29 13:02:23 +04:00
|
|
|
|
2011-04-26 17:29:34 +04:00
|
|
|
vpath = g_new0 (vfs_path_t, 1);
|
2011-09-29 13:02:23 +04:00
|
|
|
vpath->path = g_array_new (FALSE, TRUE, sizeof (vfs_path_element_t *));
|
2023-04-02 15:46:26 +03:00
|
|
|
vpath->relative = relative;
|
2011-09-29 13:02:23 +04:00
|
|
|
|
2011-04-26 17:29:34 +04:00
|
|
|
return vpath;
|
2011-04-14 16:21:30 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2011-04-28 15:39:59 +04:00
|
|
|
/*
|
|
|
|
* Get count of path elements.
|
|
|
|
*
|
|
|
|
* @param vpath pointer to vfs_path_t object
|
|
|
|
*
|
|
|
|
* @return count of path elements.
|
|
|
|
*/
|
2011-04-14 16:21:30 +04:00
|
|
|
|
2011-04-28 15:39:59 +04:00
|
|
|
int
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_elements_count (const vfs_path_t *vpath)
|
2011-04-14 16:21:30 +04:00
|
|
|
{
|
2011-09-29 13:02:23 +04:00
|
|
|
return (vpath != NULL && vpath->path != NULL) ? vpath->path->len : 0;
|
2011-04-14 16:21:30 +04:00
|
|
|
}
|
|
|
|
|
2011-11-27 04:09:41 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* Add vfs_path_element_t object to end of list in vfs_path_t object
|
|
|
|
* @param vpath pointer to vfs_path_t object
|
|
|
|
* @param path_element pointer to vfs_path_element_t object
|
|
|
|
*/
|
|
|
|
|
|
|
|
void
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_add_element (vfs_path_t *vpath, const vfs_path_element_t *path_element)
|
2011-11-27 04:09:41 +04:00
|
|
|
{
|
|
|
|
g_array_append_val (vpath->path, path_element);
|
2013-04-14 17:38:37 +04:00
|
|
|
g_free (vpath->str);
|
2016-02-20 13:13:31 +03:00
|
|
|
vpath->str = vfs_path_to_str_flags (vpath, 0, VPF_NONE);
|
2011-11-27 04:09:41 +04:00
|
|
|
}
|
|
|
|
|
2011-04-14 16:21:30 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2011-04-28 15:39:59 +04:00
|
|
|
/*
|
|
|
|
* Get one path element by index.
|
|
|
|
*
|
2022-05-07 11:02:24 +03:00
|
|
|
* @param vpath pointer to vfs_path_t object.
|
|
|
|
* May be NULL. In this case NULL is returned and errno set to 0.
|
|
|
|
* @param element_index element index. May have negative value (in this case count was started at
|
|
|
|
* the end of list). If @element_index is out of range, NULL is returned and
|
|
|
|
* errno set to EINVAL.
|
2011-04-28 15:39:59 +04:00
|
|
|
*
|
2022-05-07 11:02:24 +03:00
|
|
|
* @return path element
|
2011-04-28 15:39:59 +04:00
|
|
|
*/
|
2011-04-14 16:21:30 +04:00
|
|
|
|
2012-01-03 13:35:57 +04:00
|
|
|
const vfs_path_element_t *
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_get_by_index (const vfs_path_t *vpath, int element_index)
|
2011-04-14 16:21:30 +04:00
|
|
|
{
|
2022-05-07 11:02:24 +03:00
|
|
|
int n;
|
|
|
|
|
2012-03-12 21:46:23 +04:00
|
|
|
if (vpath == NULL)
|
2022-05-07 11:02:24 +03:00
|
|
|
{
|
|
|
|
errno = 0;
|
2012-03-12 21:46:23 +04:00
|
|
|
return NULL;
|
2022-05-07 11:02:24 +03:00
|
|
|
}
|
2012-03-12 21:46:23 +04:00
|
|
|
|
2022-05-07 11:02:24 +03:00
|
|
|
n = vfs_path_elements_count (vpath);
|
2011-04-28 15:39:59 +04:00
|
|
|
|
2011-06-29 21:52:01 +04:00
|
|
|
if (element_index < 0)
|
2022-05-07 11:02:24 +03:00
|
|
|
element_index += n;
|
|
|
|
|
|
|
|
if (element_index < 0 || element_index > n)
|
|
|
|
{
|
|
|
|
errno = EINVAL;
|
|
|
|
return NULL;
|
|
|
|
}
|
2011-06-08 17:40:36 +04:00
|
|
|
|
2011-09-29 13:02:23 +04:00
|
|
|
return g_array_index (vpath->path, vfs_path_element_t *, element_index);
|
2011-06-08 17:40:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/*
|
|
|
|
* Clone one path element
|
|
|
|
*
|
|
|
|
* @param element pointer to vfs_path_element_t object
|
|
|
|
*
|
|
|
|
* @return Newly allocated path element
|
|
|
|
*/
|
|
|
|
|
|
|
|
vfs_path_element_t *
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_element_clone (const vfs_path_element_t *element)
|
2011-06-08 17:40:36 +04:00
|
|
|
{
|
2012-03-24 20:52:01 +04:00
|
|
|
vfs_path_element_t *new_element = g_new (vfs_path_element_t, 1);
|
2011-06-08 17:40:36 +04:00
|
|
|
|
|
|
|
new_element->user = g_strdup (element->user);
|
|
|
|
new_element->password = g_strdup (element->password);
|
|
|
|
new_element->host = g_strdup (element->host);
|
2012-03-24 20:52:01 +04:00
|
|
|
new_element->ipv6 = element->ipv6;
|
|
|
|
new_element->port = element->port;
|
2011-06-08 17:40:36 +04:00
|
|
|
new_element->path = g_strdup (element->path);
|
2012-03-24 20:52:01 +04:00
|
|
|
new_element->class = element->class;
|
|
|
|
new_element->vfs_prefix = g_strdup (element->vfs_prefix);
|
2012-04-30 14:58:25 +04:00
|
|
|
#ifdef HAVE_CHARSET
|
|
|
|
new_element->encoding = g_strdup (element->encoding);
|
2024-09-13 10:26:53 +03:00
|
|
|
if (vfs_path_element_need_cleanup_converter (element) && element->encoding != NULL)
|
|
|
|
new_element->dir.converter = str_crt_conv_from (element->encoding);
|
2012-03-24 20:52:01 +04:00
|
|
|
else
|
|
|
|
new_element->dir.converter = element->dir.converter;
|
2012-04-30 14:58:25 +04:00
|
|
|
#endif
|
2012-03-24 20:52:01 +04:00
|
|
|
new_element->dir.info = element->dir.info;
|
2011-06-08 17:40:36 +04:00
|
|
|
|
|
|
|
return new_element;
|
2011-04-14 16:21:30 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2011-04-28 15:39:59 +04:00
|
|
|
/*
|
|
|
|
* Free one path element.
|
|
|
|
*
|
|
|
|
* @param element pointer to vfs_path_element_t object
|
|
|
|
*
|
|
|
|
*/
|
2011-04-14 16:21:30 +04:00
|
|
|
|
|
|
|
void
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_element_free (vfs_path_element_t *element)
|
2011-04-14 16:21:30 +04:00
|
|
|
{
|
|
|
|
if (element == NULL)
|
|
|
|
return;
|
|
|
|
|
2011-06-07 14:18:08 +04:00
|
|
|
g_free (element->user);
|
|
|
|
g_free (element->password);
|
|
|
|
g_free (element->host);
|
2011-04-18 16:08:13 +04:00
|
|
|
g_free (element->path);
|
2011-06-13 14:19:47 +04:00
|
|
|
g_free (element->vfs_prefix);
|
2011-06-01 14:56:52 +04:00
|
|
|
|
2012-04-30 14:58:25 +04:00
|
|
|
#ifdef HAVE_CHARSET
|
|
|
|
g_free (element->encoding);
|
|
|
|
|
2011-06-01 14:56:52 +04:00
|
|
|
if (vfs_path_element_need_cleanup_converter (element))
|
|
|
|
str_close_conv (element->dir.converter);
|
2012-04-30 14:58:25 +04:00
|
|
|
#endif
|
2011-06-01 14:56:52 +04:00
|
|
|
|
2011-04-18 16:08:13 +04:00
|
|
|
g_free (element);
|
2011-04-14 16:21:30 +04:00
|
|
|
}
|
|
|
|
|
2011-06-08 17:40:36 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/*
|
|
|
|
* Clone path
|
|
|
|
*
|
|
|
|
* @param vpath pointer to vfs_path_t object
|
|
|
|
*
|
|
|
|
* @return Newly allocated path object
|
|
|
|
*/
|
|
|
|
|
|
|
|
vfs_path_t *
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_clone (const vfs_path_t *vpath)
|
2011-06-08 17:40:36 +04:00
|
|
|
{
|
|
|
|
vfs_path_t *new_vpath;
|
|
|
|
int vpath_element_index;
|
2011-09-29 13:02:23 +04:00
|
|
|
|
2011-06-08 17:40:36 +04:00
|
|
|
if (vpath == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2023-04-02 15:46:26 +03:00
|
|
|
new_vpath = vfs_path_new (vpath->relative);
|
2011-09-29 13:02:23 +04:00
|
|
|
|
2011-06-08 17:40:36 +04:00
|
|
|
for (vpath_element_index = 0; vpath_element_index < vfs_path_elements_count (vpath);
|
|
|
|
vpath_element_index++)
|
|
|
|
{
|
2011-09-29 13:02:23 +04:00
|
|
|
vfs_path_element_t *path_element;
|
|
|
|
|
2012-02-07 15:54:58 +04:00
|
|
|
path_element = vfs_path_element_clone (vfs_path_get_by_index (vpath, vpath_element_index));
|
2011-09-29 13:02:23 +04:00
|
|
|
g_array_append_val (new_vpath->path, path_element);
|
2011-06-08 17:40:36 +04:00
|
|
|
}
|
2013-04-14 17:38:37 +04:00
|
|
|
new_vpath->str = g_strdup (vpath->str);
|
2011-06-08 17:40:36 +04:00
|
|
|
|
|
|
|
return new_vpath;
|
|
|
|
}
|
|
|
|
|
2011-04-14 16:21:30 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2011-04-28 15:39:59 +04:00
|
|
|
/*
|
|
|
|
* Free vfs_path_t object.
|
|
|
|
*
|
|
|
|
* @param vpath pointer to vfs_path_t object
|
2021-02-21 19:30:18 +03:00
|
|
|
* @param free_str if TRUE the string representation of vpath is freed as well
|
2011-04-28 15:39:59 +04:00
|
|
|
*
|
2021-02-21 19:30:18 +03:00
|
|
|
* @return the string representation of vpath (i.e. NULL if free_str is TRUE)
|
2011-04-28 15:39:59 +04:00
|
|
|
*/
|
2011-04-14 16:21:30 +04:00
|
|
|
|
2021-02-21 19:30:18 +03:00
|
|
|
char *
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_free (vfs_path_t *vpath, gboolean free_str)
|
2011-04-14 16:21:30 +04:00
|
|
|
{
|
2011-09-29 13:02:23 +04:00
|
|
|
int vpath_element_index;
|
2021-02-21 19:30:18 +03:00
|
|
|
char *ret;
|
2011-09-29 13:02:23 +04:00
|
|
|
|
|
|
|
if (vpath == NULL)
|
2021-02-21 19:30:18 +03:00
|
|
|
return NULL;
|
2011-09-29 13:02:23 +04:00
|
|
|
|
|
|
|
for (vpath_element_index = 0; vpath_element_index < vfs_path_elements_count (vpath);
|
|
|
|
vpath_element_index++)
|
2012-01-03 13:35:57 +04:00
|
|
|
{
|
|
|
|
vfs_path_element_t *path_element;
|
|
|
|
|
|
|
|
path_element = (vfs_path_element_t *) vfs_path_get_by_index (vpath, vpath_element_index);
|
|
|
|
vfs_path_element_free (path_element);
|
|
|
|
}
|
2011-09-29 13:02:23 +04:00
|
|
|
|
|
|
|
g_array_free (vpath->path, TRUE);
|
2021-02-21 19:30:18 +03:00
|
|
|
|
|
|
|
if (!free_str)
|
|
|
|
ret = vpath->str;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_free (vpath->str);
|
|
|
|
ret = NULL;
|
|
|
|
}
|
|
|
|
|
2011-09-29 13:02:23 +04:00
|
|
|
g_free (vpath);
|
2021-02-21 19:30:18 +03:00
|
|
|
|
|
|
|
return ret;
|
2011-04-14 16:21:30 +04:00
|
|
|
}
|
|
|
|
|
2011-06-08 17:40:36 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/*
|
|
|
|
* Remove one path element by index
|
|
|
|
*
|
|
|
|
* @param vpath pointer to vfs_path_t object
|
|
|
|
* @param element_index element index. May have negative value (in this case count was started at the end of list).
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
void
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_remove_element_by_index (vfs_path_t *vpath, int element_index)
|
2011-06-08 17:40:36 +04:00
|
|
|
{
|
|
|
|
vfs_path_element_t *element;
|
|
|
|
|
|
|
|
if ((vpath == NULL) || (vfs_path_elements_count (vpath) == 1))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (element_index < 0)
|
|
|
|
element_index = vfs_path_elements_count (vpath) + element_index;
|
|
|
|
|
2012-01-03 13:35:57 +04:00
|
|
|
element = (vfs_path_element_t *) vfs_path_get_by_index (vpath, element_index);
|
2011-09-29 13:02:23 +04:00
|
|
|
vpath->path = g_array_remove_index (vpath->path, element_index);
|
2011-06-08 17:40:36 +04:00
|
|
|
vfs_path_element_free (element);
|
2013-04-14 17:38:37 +04:00
|
|
|
g_free (vpath->str);
|
|
|
|
vpath->str = vfs_path_to_str_flags (vpath, 0, VPF_NONE);
|
2011-06-08 17:40:36 +04:00
|
|
|
}
|
|
|
|
|
2011-04-14 16:21:30 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2011-04-28 15:39:59 +04:00
|
|
|
/** Return VFS class for the given prefix */
|
2011-06-14 12:55:27 +04:00
|
|
|
|
2011-04-28 15:39:59 +04:00
|
|
|
struct vfs_class *
|
|
|
|
vfs_prefix_to_class (const char *prefix)
|
|
|
|
{
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
/* Avoid first class (localfs) that would accept any prefix */
|
|
|
|
for (i = 1; i < vfs__classes_list->len; i++)
|
|
|
|
{
|
2012-01-03 13:35:57 +04:00
|
|
|
struct vfs_class *vfs;
|
|
|
|
|
2018-09-12 14:01:28 +03:00
|
|
|
vfs = VFS_CLASS (g_ptr_array_index (vfs__classes_list, i));
|
2011-04-28 15:39:59 +04:00
|
|
|
if (vfs->which != NULL)
|
|
|
|
{
|
|
|
|
if (vfs->which (vfs, prefix) == -1)
|
|
|
|
continue;
|
|
|
|
return vfs;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vfs->prefix != NULL && strncmp (prefix, vfs->prefix, strlen (vfs->prefix)) == 0)
|
|
|
|
return vfs;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2012-08-31 18:05:29 +04:00
|
|
|
|
|
|
|
#ifdef HAVE_CHARSET
|
|
|
|
|
2024-10-03 14:29:28 +03:00
|
|
|
/** get encoding after last #enc: or NULL, if part does not contain #enc:
|
|
|
|
*
|
|
|
|
* @param path null-terminated string
|
|
|
|
* @param len the maximum length of path, where #enc: should be searched
|
|
|
|
*
|
|
|
|
* @return newly allocated string.
|
|
|
|
*/
|
|
|
|
|
|
|
|
char *
|
|
|
|
vfs_get_encoding (const char *path, ssize_t len)
|
|
|
|
{
|
|
|
|
char *semi;
|
|
|
|
|
|
|
|
/* try found #enc: */
|
|
|
|
semi = g_strrstr_len (path, len, VFS_ENCODING_PREFIX);
|
|
|
|
if (semi == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (semi == path || IS_PATH_SEP (semi[-1]))
|
|
|
|
{
|
|
|
|
char *slash;
|
|
|
|
|
|
|
|
semi += strlen (VFS_ENCODING_PREFIX); /* skip "#enc:" */
|
|
|
|
slash = strchr (semi, PATH_SEP);
|
|
|
|
if (slash != NULL)
|
|
|
|
return g_strndup (semi, slash - semi);
|
|
|
|
return g_strdup (semi);
|
|
|
|
}
|
|
|
|
|
|
|
|
return vfs_get_encoding (path, semi - path);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2011-06-01 14:56:52 +04:00
|
|
|
/**
|
|
|
|
* Check if need cleanup charset converter for vfs_path_element_t
|
|
|
|
*
|
|
|
|
* @param element part of path
|
|
|
|
*
|
|
|
|
* @return TRUE if need cleanup converter or FALSE otherwise
|
|
|
|
*/
|
2012-08-31 18:05:29 +04:00
|
|
|
|
2011-06-01 14:56:52 +04:00
|
|
|
gboolean
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_element_need_cleanup_converter (const vfs_path_element_t *element)
|
2011-06-01 14:56:52 +04:00
|
|
|
{
|
|
|
|
return (element->dir.converter != str_cnv_from_term && element->dir.converter != INVALID_CONV);
|
|
|
|
}
|
2013-07-22 16:25:12 +04:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* Change encoding for last part (vfs_path_element_t) of vpath
|
|
|
|
*
|
|
|
|
* @param vpath pointer to path structure
|
|
|
|
* encoding name of charset
|
|
|
|
*
|
Fix various typos in the source code (closes MidnightCommander/mc#177).
Found via `codespell -S
po,doc,./misc/syntax,./src/vfs/extfs/helpers/README.it -L
parm,rouge,sav,ect,vie,te,dum,clen,wee,dynamc,childs,ths,fo,nin,unx,nd,iif,iterm,ser,makrs,wil`
Co-authored-by: Yury V. Zaytsev <yury@shurup.com>
Signed-off-by: Kian-Meng Ang <kianmeng@cpan.org>
Signed-off-by: Yury V. Zaytsev <yury@shurup.com>
2023-01-10 06:02:52 +03:00
|
|
|
* @return pointer to path structure (for use function in another functions)
|
2013-07-22 16:25:12 +04:00
|
|
|
*/
|
|
|
|
vfs_path_t *
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_change_encoding (vfs_path_t *vpath, const char *encoding)
|
2013-07-22 16:25:12 +04:00
|
|
|
{
|
|
|
|
vfs_path_element_t *path_element;
|
|
|
|
|
|
|
|
path_element = (vfs_path_element_t *) vfs_path_get_by_index (vpath, -1);
|
|
|
|
/* don't add current encoding */
|
|
|
|
if ((path_element->encoding != NULL) && (strcmp (encoding, path_element->encoding) == 0))
|
|
|
|
return vpath;
|
|
|
|
|
|
|
|
g_free (path_element->encoding);
|
|
|
|
path_element->encoding = g_strdup (encoding);
|
|
|
|
|
|
|
|
if (vfs_path_element_need_cleanup_converter (path_element))
|
|
|
|
str_close_conv (path_element->dir.converter);
|
|
|
|
|
|
|
|
path_element->dir.converter = str_crt_conv_from (path_element->encoding);
|
|
|
|
|
|
|
|
g_free (vpath->str);
|
|
|
|
vpath->str = vfs_path_to_str_flags (vpath, 0, VPF_NONE);
|
|
|
|
return vpath;
|
|
|
|
}
|
|
|
|
|
2012-04-30 14:58:25 +04:00
|
|
|
#endif
|
2011-06-01 14:56:52 +04:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2012-08-31 18:05:29 +04:00
|
|
|
|
2011-06-07 13:22:31 +04:00
|
|
|
/**
|
|
|
|
* Serialize vfs_path_t object to string
|
|
|
|
*
|
|
|
|
* @param vpath data for serialization
|
|
|
|
* @param error contain pointer to object for handle error code and message
|
|
|
|
*
|
2012-11-05 17:57:50 +04:00
|
|
|
* @return serialized vpath as newly allocated string
|
2011-06-07 13:22:31 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
char *
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_serialize (const vfs_path_t *vpath, GError **mcerror)
|
2011-06-07 13:22:31 +04:00
|
|
|
{
|
2012-07-28 14:19:27 +04:00
|
|
|
mc_config_t *cpath;
|
2011-06-07 13:22:31 +04:00
|
|
|
ssize_t element_index;
|
|
|
|
char *ret_value;
|
|
|
|
|
2014-07-15 16:53:06 +04:00
|
|
|
mc_return_val_if_error (mcerror, FALSE);
|
|
|
|
|
2011-06-07 13:22:31 +04:00
|
|
|
if ((vpath == NULL) || (vfs_path_elements_count (vpath) == 0))
|
|
|
|
{
|
2016-01-03 14:13:02 +03:00
|
|
|
mc_propagate_error (mcerror, 0, "%s", "vpath object is empty");
|
2011-06-07 13:22:31 +04:00
|
|
|
return NULL;
|
|
|
|
}
|
2012-07-28 14:19:27 +04:00
|
|
|
|
|
|
|
cpath = mc_config_init (NULL, FALSE);
|
|
|
|
|
2011-06-07 13:22:31 +04:00
|
|
|
for (element_index = 0; element_index < vfs_path_elements_count (vpath); element_index++)
|
|
|
|
{
|
2016-10-03 09:18:09 +03:00
|
|
|
char groupname[BUF_TINY];
|
2012-01-03 13:35:57 +04:00
|
|
|
const vfs_path_element_t *element;
|
2011-06-07 13:22:31 +04:00
|
|
|
|
2016-10-03 09:18:09 +03:00
|
|
|
g_snprintf (groupname, sizeof (groupname), "path-element-%zd", element_index);
|
2012-01-03 13:35:57 +04:00
|
|
|
element = vfs_path_get_by_index (vpath, element_index);
|
2011-06-07 13:22:31 +04:00
|
|
|
/* convert one element to config group */
|
|
|
|
|
|
|
|
mc_config_set_string_raw (cpath, groupname, "path", element->path);
|
|
|
|
mc_config_set_string_raw (cpath, groupname, "class-name", element->class->name);
|
2012-04-30 14:58:25 +04:00
|
|
|
#ifdef HAVE_CHARSET
|
2011-06-07 13:22:31 +04:00
|
|
|
mc_config_set_string_raw (cpath, groupname, "encoding", element->encoding);
|
2012-04-30 14:58:25 +04:00
|
|
|
#endif
|
2011-06-13 14:19:47 +04:00
|
|
|
mc_config_set_string_raw (cpath, groupname, "vfs_prefix", element->vfs_prefix);
|
2011-06-07 13:22:31 +04:00
|
|
|
|
2011-06-07 14:18:08 +04:00
|
|
|
mc_config_set_string_raw (cpath, groupname, "user", element->user);
|
|
|
|
mc_config_set_string_raw (cpath, groupname, "password", element->password);
|
|
|
|
mc_config_set_string_raw (cpath, groupname, "host", element->host);
|
2011-06-13 14:19:47 +04:00
|
|
|
if (element->port != 0)
|
|
|
|
mc_config_set_int (cpath, groupname, "port", element->port);
|
2011-06-07 13:22:31 +04:00
|
|
|
}
|
|
|
|
|
2014-07-15 16:53:06 +04:00
|
|
|
ret_value = mc_serialize_config (cpath, mcerror);
|
2011-06-07 13:22:31 +04:00
|
|
|
mc_config_deinit (cpath);
|
|
|
|
return ret_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* Deserialize string to vfs_path_t object
|
|
|
|
*
|
|
|
|
* @param data data for serialization
|
|
|
|
* @param error contain pointer to object for handle error code and message
|
|
|
|
*
|
|
|
|
* @return newly allocated vfs_path_t object
|
|
|
|
*/
|
|
|
|
|
|
|
|
vfs_path_t *
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_deserialize (const char *data, GError **mcerror)
|
2011-06-07 13:22:31 +04:00
|
|
|
{
|
2012-07-28 14:19:27 +04:00
|
|
|
mc_config_t *cpath;
|
2016-10-03 09:34:15 +03:00
|
|
|
size_t element_index;
|
2011-06-07 13:22:31 +04:00
|
|
|
vfs_path_t *vpath;
|
|
|
|
|
2014-07-15 16:53:06 +04:00
|
|
|
mc_return_val_if_error (mcerror, FALSE);
|
|
|
|
|
|
|
|
cpath = mc_deserialize_config (data, mcerror);
|
2011-06-07 13:22:31 +04:00
|
|
|
if (cpath == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2023-04-02 15:46:26 +03:00
|
|
|
vpath = vfs_path_new (FALSE);
|
2011-06-07 13:22:31 +04:00
|
|
|
|
2016-10-03 09:34:15 +03:00
|
|
|
for (element_index = 0;; element_index++)
|
2011-06-07 13:22:31 +04:00
|
|
|
{
|
2016-10-03 09:34:15 +03:00
|
|
|
struct vfs_class *eclass;
|
2011-06-07 13:22:31 +04:00
|
|
|
vfs_path_element_t *element;
|
|
|
|
char *cfg_value;
|
2016-10-03 09:34:15 +03:00
|
|
|
char groupname[BUF_TINY];
|
2011-06-07 13:22:31 +04:00
|
|
|
|
2016-10-03 09:34:15 +03:00
|
|
|
g_snprintf (groupname, sizeof (groupname), "path-element-%zu", element_index);
|
2011-06-07 13:22:31 +04:00
|
|
|
if (!mc_config_has_group (cpath, groupname))
|
|
|
|
break;
|
|
|
|
|
|
|
|
cfg_value = mc_config_get_string_raw (cpath, groupname, "class-name", NULL);
|
2016-10-03 09:34:15 +03:00
|
|
|
eclass = vfs_get_class_by_name (cfg_value);
|
|
|
|
if (eclass == NULL)
|
2011-06-07 13:22:31 +04:00
|
|
|
{
|
2021-02-21 19:30:18 +03:00
|
|
|
vfs_path_free (vpath, TRUE);
|
2016-01-03 14:13:02 +03:00
|
|
|
g_set_error (mcerror, MC_ERROR, 0, "Unable to find VFS class by name '%s'", cfg_value);
|
2011-06-07 13:22:31 +04:00
|
|
|
g_free (cfg_value);
|
|
|
|
mc_config_deinit (cpath);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
g_free (cfg_value);
|
|
|
|
|
2016-10-03 09:34:15 +03:00
|
|
|
element = g_new0 (vfs_path_element_t, 1);
|
|
|
|
element->class = eclass;
|
2011-06-07 13:22:31 +04:00
|
|
|
element->path = mc_config_get_string_raw (cpath, groupname, "path", NULL);
|
2012-04-30 14:58:25 +04:00
|
|
|
|
|
|
|
#ifdef HAVE_CHARSET
|
2011-06-07 13:22:31 +04:00
|
|
|
element->encoding = mc_config_get_string_raw (cpath, groupname, "encoding", NULL);
|
2011-08-15 15:37:59 +04:00
|
|
|
element->dir.converter =
|
|
|
|
(element->encoding != NULL) ? str_crt_conv_from (element->encoding) : INVALID_CONV;
|
2012-04-30 14:58:25 +04:00
|
|
|
#endif
|
2011-06-07 13:22:31 +04:00
|
|
|
|
2011-06-13 14:19:47 +04:00
|
|
|
element->vfs_prefix = mc_config_get_string_raw (cpath, groupname, "vfs_prefix", NULL);
|
2011-06-07 13:22:31 +04:00
|
|
|
|
2011-06-07 14:18:08 +04:00
|
|
|
element->user = mc_config_get_string_raw (cpath, groupname, "user", NULL);
|
|
|
|
element->password = mc_config_get_string_raw (cpath, groupname, "password", NULL);
|
|
|
|
element->host = mc_config_get_string_raw (cpath, groupname, "host", NULL);
|
|
|
|
element->port = mc_config_get_int (cpath, groupname, "port", 0);
|
|
|
|
|
2011-09-29 13:02:23 +04:00
|
|
|
vpath->path = g_array_append_val (vpath->path, element);
|
2011-06-07 13:22:31 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
mc_config_deinit (cpath);
|
|
|
|
if (vfs_path_elements_count (vpath) == 0)
|
|
|
|
{
|
2021-02-21 19:30:18 +03:00
|
|
|
vfs_path_free (vpath, TRUE);
|
2016-01-03 14:13:02 +03:00
|
|
|
g_set_error (mcerror, MC_ERROR, 0, "No any path elements found");
|
2011-06-07 13:22:31 +04:00
|
|
|
return NULL;
|
|
|
|
}
|
2013-04-14 17:38:37 +04:00
|
|
|
vpath->str = vfs_path_to_str_flags (vpath, 0, VPF_NONE);
|
2011-06-07 13:22:31 +04:00
|
|
|
|
|
|
|
return vpath;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2011-07-17 20:59:47 +04:00
|
|
|
/**
|
|
|
|
* Build vfs_path_t object from arguments.
|
2011-08-01 00:44:15 +04:00
|
|
|
*
|
2012-08-31 18:05:29 +04:00
|
|
|
* @param first_element of path
|
2011-08-01 00:44:15 +04:00
|
|
|
* @param ... path tokens, terminated by NULL
|
|
|
|
*
|
|
|
|
* @return newly allocated vfs_path_t object
|
2011-07-17 20:59:47 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
vfs_path_t *
|
|
|
|
vfs_path_build_filename (const char *first_element, ...)
|
|
|
|
{
|
|
|
|
va_list args;
|
|
|
|
char *str_path;
|
|
|
|
vfs_path_t *vpath;
|
|
|
|
|
|
|
|
if (first_element == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
va_start (args, first_element);
|
|
|
|
str_path = mc_build_filenamev (first_element, args);
|
|
|
|
va_end (args);
|
|
|
|
vpath = vfs_path_from_str (str_path);
|
|
|
|
g_free (str_path);
|
|
|
|
return vpath;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2011-08-01 00:44:15 +04:00
|
|
|
/**
|
|
|
|
* Append tokens to path object
|
|
|
|
*
|
|
|
|
* @param vpath path object
|
2012-08-31 18:05:29 +04:00
|
|
|
* @param first_element of path
|
2011-08-01 00:44:15 +04:00
|
|
|
* @param ... NULL-terminated strings
|
|
|
|
*
|
|
|
|
* @return newly allocated path object
|
|
|
|
*/
|
2011-07-18 22:07:39 +04:00
|
|
|
|
|
|
|
vfs_path_t *
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_append_new (const vfs_path_t *vpath, const char *first_element, ...)
|
2011-07-18 22:07:39 +04:00
|
|
|
{
|
|
|
|
va_list args;
|
2013-04-14 17:38:37 +04:00
|
|
|
char *str_path;
|
|
|
|
const char *result_str;
|
2011-07-18 22:07:39 +04:00
|
|
|
vfs_path_t *ret_vpath;
|
|
|
|
|
|
|
|
if (vpath == NULL || first_element == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
va_start (args, first_element);
|
|
|
|
str_path = mc_build_filenamev (first_element, args);
|
|
|
|
va_end (args);
|
|
|
|
|
2013-04-14 17:38:37 +04:00
|
|
|
result_str = vfs_path_as_str (vpath);
|
2016-03-25 21:33:44 +03:00
|
|
|
ret_vpath = vfs_path_build_filename (result_str, str_path, (char *) NULL);
|
2011-07-18 22:07:39 +04:00
|
|
|
g_free (str_path);
|
|
|
|
|
|
|
|
return ret_vpath;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2011-09-25 15:36:44 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Append vpath_t tokens to path object
|
|
|
|
*
|
2012-08-31 18:05:29 +04:00
|
|
|
* @param first_vpath vpath objects
|
2011-09-25 15:36:44 +04:00
|
|
|
* @param ... NULL-terminated vpath objects
|
|
|
|
*
|
|
|
|
* @return newly allocated path object
|
|
|
|
*/
|
|
|
|
|
|
|
|
vfs_path_t *
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_append_vpath_new (const vfs_path_t *first_vpath, ...)
|
2011-09-25 15:36:44 +04:00
|
|
|
{
|
|
|
|
va_list args;
|
|
|
|
vfs_path_t *ret_vpath;
|
|
|
|
const vfs_path_t *current_vpath = first_vpath;
|
|
|
|
|
|
|
|
if (first_vpath == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2023-04-02 15:46:26 +03:00
|
|
|
ret_vpath = vfs_path_new (FALSE);
|
2011-09-25 15:36:44 +04:00
|
|
|
|
|
|
|
va_start (args, first_vpath);
|
|
|
|
do
|
|
|
|
{
|
|
|
|
int vindex;
|
|
|
|
|
|
|
|
for (vindex = 0; vindex < vfs_path_elements_count (current_vpath); vindex++)
|
2011-09-29 13:02:23 +04:00
|
|
|
{
|
|
|
|
vfs_path_element_t *path_element;
|
|
|
|
|
2012-02-07 15:54:58 +04:00
|
|
|
path_element = vfs_path_element_clone (vfs_path_get_by_index (current_vpath, vindex));
|
2011-09-29 13:02:23 +04:00
|
|
|
g_array_append_val (ret_vpath->path, path_element);
|
|
|
|
}
|
2011-09-25 15:36:44 +04:00
|
|
|
current_vpath = va_arg (args, const vfs_path_t *);
|
|
|
|
}
|
|
|
|
while (current_vpath != NULL);
|
|
|
|
va_end (args);
|
|
|
|
|
2013-04-14 17:38:37 +04:00
|
|
|
ret_vpath->str = vfs_path_to_str_flags (ret_vpath, 0, VPF_NONE);
|
|
|
|
|
2011-09-25 15:36:44 +04:00
|
|
|
return ret_vpath;
|
|
|
|
}
|
|
|
|
|
2011-07-18 22:07:39 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2012-08-31 18:05:29 +04:00
|
|
|
|
2011-08-01 00:44:15 +04:00
|
|
|
/**
|
2024-10-05 19:55:01 +03:00
|
|
|
* get tokens count in path.
|
2011-08-01 00:44:15 +04:00
|
|
|
*
|
|
|
|
* @param vpath path object
|
|
|
|
*
|
|
|
|
* @return count of tokens
|
|
|
|
*/
|
|
|
|
|
|
|
|
size_t
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_tokens_count (const vfs_path_t *vpath)
|
2011-08-01 00:44:15 +04:00
|
|
|
{
|
|
|
|
size_t count_tokens = 0;
|
|
|
|
int element_index;
|
|
|
|
|
|
|
|
if (vpath == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
for (element_index = 0; element_index < vfs_path_elements_count (vpath); element_index++)
|
|
|
|
{
|
2012-01-03 13:35:57 +04:00
|
|
|
const vfs_path_element_t *element;
|
2013-08-07 13:20:22 +04:00
|
|
|
const char *token, *prev_token;
|
2011-08-01 00:44:15 +04:00
|
|
|
|
|
|
|
element = vfs_path_get_by_index (vpath, element_index);
|
|
|
|
|
2013-08-07 13:20:22 +04:00
|
|
|
for (prev_token = element->path; (token = strchr (prev_token, PATH_SEP)) != NULL;
|
|
|
|
prev_token = token + 1)
|
2011-08-01 00:44:15 +04:00
|
|
|
{
|
2013-08-07 13:20:22 +04:00
|
|
|
/* skip empty substring */
|
|
|
|
if (token != prev_token)
|
2011-08-01 00:44:15 +04:00
|
|
|
count_tokens++;
|
|
|
|
}
|
2013-08-07 13:20:22 +04:00
|
|
|
|
|
|
|
if (*prev_token != '\0')
|
|
|
|
count_tokens++;
|
2011-08-01 00:44:15 +04:00
|
|
|
}
|
2013-08-07 13:20:22 +04:00
|
|
|
|
2011-08-01 00:44:15 +04:00
|
|
|
return count_tokens;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2012-08-31 18:05:29 +04:00
|
|
|
|
2011-08-01 00:44:15 +04:00
|
|
|
/**
|
|
|
|
* Get subpath by tokens
|
|
|
|
*
|
|
|
|
* @param vpath path object
|
|
|
|
* @param start_position first token for got/ Started from 0.
|
|
|
|
* If negative, then position will be relative to end of path
|
|
|
|
* @param length count of tokens
|
|
|
|
*
|
|
|
|
* @return newly allocated string with path tokens separated by slash
|
|
|
|
*/
|
|
|
|
|
|
|
|
char *
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_tokens_get (const vfs_path_t *vpath, ssize_t start_position, ssize_t length)
|
2011-08-01 00:44:15 +04:00
|
|
|
{
|
|
|
|
GString *ret_tokens, *element_tokens;
|
|
|
|
int element_index;
|
|
|
|
size_t tokens_count = vfs_path_tokens_count (vpath);
|
|
|
|
|
2011-09-25 15:36:44 +04:00
|
|
|
if (vpath == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2011-08-01 00:44:15 +04:00
|
|
|
if (length == 0)
|
|
|
|
length = tokens_count;
|
|
|
|
|
2011-11-08 23:44:38 +04:00
|
|
|
if (length < 0)
|
|
|
|
length = tokens_count + length;
|
|
|
|
|
2011-08-01 00:44:15 +04:00
|
|
|
if (start_position < 0)
|
|
|
|
start_position = (ssize_t) tokens_count + start_position;
|
|
|
|
|
|
|
|
if (start_position < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (start_position >= (ssize_t) tokens_count)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (start_position + (ssize_t) length > (ssize_t) tokens_count)
|
|
|
|
length = tokens_count - start_position;
|
|
|
|
|
|
|
|
ret_tokens = g_string_sized_new (32);
|
|
|
|
element_tokens = g_string_sized_new (32);
|
|
|
|
|
|
|
|
for (element_index = 0; element_index < vfs_path_elements_count (vpath); element_index++)
|
|
|
|
{
|
2012-01-03 13:35:57 +04:00
|
|
|
const vfs_path_element_t *element;
|
2011-08-01 00:44:15 +04:00
|
|
|
char **path_tokens, **iterator;
|
|
|
|
|
|
|
|
g_string_assign (element_tokens, "");
|
|
|
|
element = vfs_path_get_by_index (vpath, element_index);
|
2013-08-07 13:44:51 +04:00
|
|
|
path_tokens = g_strsplit (element->path, PATH_SEP_STR, -1);
|
2011-08-01 00:44:15 +04:00
|
|
|
|
2013-08-07 13:44:51 +04:00
|
|
|
for (iterator = path_tokens; *iterator != NULL; iterator++)
|
2011-08-01 00:44:15 +04:00
|
|
|
{
|
|
|
|
if (**iterator != '\0')
|
|
|
|
{
|
|
|
|
if (start_position == 0)
|
|
|
|
{
|
|
|
|
if (length == 0)
|
|
|
|
{
|
|
|
|
vfs_path_tokens_add_class_info (element, ret_tokens, element_tokens);
|
|
|
|
g_string_free (element_tokens, TRUE);
|
|
|
|
g_strfreev (path_tokens);
|
|
|
|
return g_string_free (ret_tokens, FALSE);
|
|
|
|
}
|
|
|
|
length--;
|
|
|
|
if (element_tokens->len != 0)
|
|
|
|
g_string_append_c (element_tokens, PATH_SEP);
|
|
|
|
g_string_append (element_tokens, *iterator);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
start_position--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_strfreev (path_tokens);
|
|
|
|
vfs_path_tokens_add_class_info (element, ret_tokens, element_tokens);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_string_free (element_tokens, TRUE);
|
|
|
|
return g_string_free (ret_tokens, !(start_position == 0 && length == 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2011-09-25 15:36:44 +04:00
|
|
|
/**
|
|
|
|
* Get subpath by tokens
|
|
|
|
*
|
|
|
|
* @param vpath path object
|
|
|
|
* @param start_position first token for got/ Started from 0.
|
|
|
|
* If negative, then position will be relative to end of path
|
|
|
|
* @param length count of tokens
|
|
|
|
*
|
|
|
|
* @return newly allocated path object with path tokens separated by slash
|
|
|
|
*/
|
|
|
|
|
|
|
|
vfs_path_t *
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_vtokens_get (const vfs_path_t *vpath, ssize_t start_position, ssize_t length)
|
2011-09-25 15:36:44 +04:00
|
|
|
{
|
|
|
|
char *str_tokens;
|
|
|
|
vfs_path_t *ret_vpath = NULL;
|
|
|
|
|
|
|
|
str_tokens = vfs_path_tokens_get (vpath, start_position, length);
|
|
|
|
if (str_tokens != NULL)
|
|
|
|
{
|
|
|
|
ret_vpath = vfs_path_from_str_flags (str_tokens, VPF_NO_CANON);
|
|
|
|
g_free (str_tokens);
|
|
|
|
}
|
|
|
|
return ret_vpath;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2012-08-31 18:05:29 +04:00
|
|
|
|
2011-09-28 00:31:20 +04:00
|
|
|
/**
|
2012-08-31 18:05:29 +04:00
|
|
|
* Build URL parameters (such as user:pass @ host:port) from one path element object
|
2011-09-28 00:31:20 +04:00
|
|
|
*
|
|
|
|
* @param element path element
|
2012-08-31 18:05:29 +04:00
|
|
|
* @param keep_password TRUE or FALSE
|
2011-09-28 00:31:20 +04:00
|
|
|
*
|
2023-08-27 12:39:04 +03:00
|
|
|
* @return newly allocated non-empty string or NULL
|
2011-09-28 00:31:20 +04:00
|
|
|
*/
|
|
|
|
|
2022-10-30 09:28:25 +03:00
|
|
|
GString *
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_build_url_params_str (const vfs_path_element_t *element, gboolean keep_password)
|
2011-09-28 00:31:20 +04:00
|
|
|
{
|
|
|
|
GString *buffer;
|
|
|
|
|
|
|
|
if (element == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2022-10-30 09:28:25 +03:00
|
|
|
buffer = g_string_sized_new (64);
|
2011-09-28 00:31:20 +04:00
|
|
|
|
|
|
|
if (element->user != NULL)
|
|
|
|
g_string_append (buffer, element->user);
|
|
|
|
|
|
|
|
if (element->password != NULL && keep_password)
|
|
|
|
{
|
|
|
|
g_string_append_c (buffer, ':');
|
|
|
|
g_string_append (buffer, element->password);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (element->host != NULL)
|
|
|
|
{
|
|
|
|
if ((element->user != NULL) || (element->password != NULL))
|
|
|
|
g_string_append_c (buffer, '@');
|
|
|
|
if (element->ipv6)
|
|
|
|
g_string_append_c (buffer, '[');
|
|
|
|
g_string_append (buffer, element->host);
|
|
|
|
if (element->ipv6)
|
|
|
|
g_string_append_c (buffer, ']');
|
|
|
|
|
2024-05-21 21:48:17 +03:00
|
|
|
if (element->port != 0)
|
|
|
|
g_string_append_printf (buffer, ":%d", element->port);
|
2011-09-28 00:31:20 +04:00
|
|
|
}
|
|
|
|
|
2023-08-27 12:39:04 +03:00
|
|
|
if (buffer->len != 0)
|
|
|
|
return buffer;
|
|
|
|
|
|
|
|
g_string_free (buffer, TRUE);
|
|
|
|
return NULL;
|
2011-09-28 00:31:20 +04:00
|
|
|
}
|
|
|
|
|
2012-04-20 15:03:53 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* Build pretty string representation of one path_element_t object
|
|
|
|
*
|
|
|
|
* @param element path element
|
|
|
|
*
|
|
|
|
* @return newly allocated string
|
|
|
|
*/
|
|
|
|
|
2022-10-30 09:13:58 +03:00
|
|
|
GString *
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_element_build_pretty_path_str (const vfs_path_element_t *element)
|
2012-04-20 15:03:53 +04:00
|
|
|
{
|
2022-10-30 09:28:25 +03:00
|
|
|
GString *url_params, *pretty_path;
|
2012-04-20 15:03:53 +04:00
|
|
|
|
|
|
|
pretty_path = g_string_new (element->class->prefix);
|
|
|
|
g_string_append (pretty_path, VFS_PATH_URL_DELIMITER);
|
|
|
|
|
|
|
|
url_params = vfs_path_build_url_params_str (element, FALSE);
|
2023-08-27 12:39:04 +03:00
|
|
|
if (url_params != NULL)
|
|
|
|
{
|
|
|
|
g_string_append_len (pretty_path, url_params->str, url_params->len);
|
|
|
|
g_string_free (url_params, TRUE);
|
|
|
|
}
|
2012-04-20 15:03:53 +04:00
|
|
|
|
2015-01-07 11:34:53 +03:00
|
|
|
if (!IS_PATH_SEP (*element->path))
|
2012-04-20 15:03:53 +04:00
|
|
|
g_string_append_c (pretty_path, PATH_SEP);
|
|
|
|
|
2023-08-27 12:39:04 +03:00
|
|
|
return g_string_append (pretty_path, element->path);
|
2012-04-20 15:03:53 +04:00
|
|
|
}
|
|
|
|
|
2011-09-28 00:31:20 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2011-10-04 13:32:14 +04:00
|
|
|
/**
|
|
|
|
* Compare two path objects as strings
|
|
|
|
*
|
|
|
|
* @param vpath1 first path object
|
|
|
|
* @param vpath2 second vpath object
|
|
|
|
*
|
|
|
|
* @return integer value like to strcmp.
|
|
|
|
*/
|
|
|
|
|
2013-01-28 17:20:42 +04:00
|
|
|
gboolean
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_equal (const vfs_path_t *vpath1, const vfs_path_t *vpath2)
|
2011-10-04 13:32:14 +04:00
|
|
|
{
|
2013-04-14 17:38:37 +04:00
|
|
|
const char *path1, *path2;
|
2013-01-28 17:20:42 +04:00
|
|
|
gboolean ret_val;
|
2011-10-04 13:32:14 +04:00
|
|
|
|
|
|
|
if (vpath1 == NULL || vpath2 == NULL)
|
2013-01-28 17:20:42 +04:00
|
|
|
return FALSE;
|
2011-10-04 13:32:14 +04:00
|
|
|
|
2013-04-14 17:38:37 +04:00
|
|
|
path1 = vfs_path_as_str (vpath1);
|
|
|
|
path2 = vfs_path_as_str (vpath2);
|
2011-10-04 13:32:14 +04:00
|
|
|
|
2013-01-28 17:20:42 +04:00
|
|
|
ret_val = strcmp (path1, path2) == 0;
|
2011-10-04 13:32:14 +04:00
|
|
|
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* Compare two path objects as strings
|
|
|
|
*
|
|
|
|
* @param vpath1 first path object
|
|
|
|
* @param vpath2 second vpath object
|
|
|
|
* @param len number of first 'len' characters
|
|
|
|
*
|
|
|
|
* @return integer value like to strcmp.
|
|
|
|
*/
|
|
|
|
|
2013-01-28 17:20:42 +04:00
|
|
|
gboolean
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_equal_len (const vfs_path_t *vpath1, const vfs_path_t *vpath2, size_t len)
|
2011-10-04 13:32:14 +04:00
|
|
|
{
|
2013-04-14 17:38:37 +04:00
|
|
|
const char *path1, *path2;
|
2013-01-28 17:20:42 +04:00
|
|
|
gboolean ret_val;
|
2011-10-04 13:32:14 +04:00
|
|
|
|
|
|
|
if (vpath1 == NULL || vpath2 == NULL)
|
2013-01-28 17:20:42 +04:00
|
|
|
return FALSE;
|
2011-10-04 13:32:14 +04:00
|
|
|
|
2013-04-14 17:38:37 +04:00
|
|
|
path1 = vfs_path_as_str (vpath1);
|
|
|
|
path2 = vfs_path_as_str (vpath2);
|
2011-10-04 13:32:14 +04:00
|
|
|
|
2013-01-28 17:20:42 +04:00
|
|
|
ret_val = strncmp (path1, path2, len) == 0;
|
2011-10-04 13:32:14 +04:00
|
|
|
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2011-10-04 15:04:48 +04:00
|
|
|
/**
|
|
|
|
* Calculate path length in string representation
|
|
|
|
*
|
|
|
|
* @param vpath path object
|
|
|
|
*
|
|
|
|
* @return length of path
|
|
|
|
*/
|
|
|
|
|
|
|
|
size_t
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_len (const vfs_path_t *vpath)
|
2011-10-04 15:04:48 +04:00
|
|
|
{
|
|
|
|
if (vpath == NULL)
|
|
|
|
return 0;
|
|
|
|
|
2013-04-14 17:38:37 +04:00
|
|
|
return strlen (vpath->str);
|
2011-10-04 15:04:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2012-02-07 15:54:58 +04:00
|
|
|
/**
|
|
|
|
* Convert relative vpath object to absolute
|
|
|
|
*
|
|
|
|
* @param vpath path object
|
|
|
|
*
|
|
|
|
* @return absolute path object
|
|
|
|
*/
|
|
|
|
|
|
|
|
vfs_path_t *
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_path_to_absolute (const vfs_path_t *vpath)
|
2012-02-07 15:54:58 +04:00
|
|
|
{
|
|
|
|
vfs_path_t *absolute_vpath;
|
2013-04-14 17:38:37 +04:00
|
|
|
const char *path_str;
|
2012-02-07 15:54:58 +04:00
|
|
|
|
|
|
|
if (!vpath->relative)
|
|
|
|
return vfs_path_clone (vpath);
|
|
|
|
|
2013-04-14 17:38:37 +04:00
|
|
|
path_str = vfs_path_as_str (vpath);
|
2012-02-07 15:54:58 +04:00
|
|
|
absolute_vpath = vfs_path_from_str (path_str);
|
|
|
|
return absolute_vpath;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|