2 Virtual File System path handlers
5 The Free Software Foundation, Inc.
8 Slava Zanko <slavazanko@gmail.com>, 2011
10 This file is part of the Midnight Commander.
12 The Midnight Commander is free software: you can redistribute it
13 and/or modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation, either version 3 of the License,
15 or (at your option) any later version.
17 The Midnight Commander is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 * \brief Source: Virtual File System: path handlers
36 #include "lib/global.h"
37 #include "lib/strutil.h"
38 #include "lib/util.h" /* concat_dir_and_file */
39 #include "lib/serialize.h"
43 #include "xdirentry.h"
46 extern GPtrArray
*vfs__classes_list
;
48 /*** global variables ****************************************************************************/
50 /*** file scope macro definitions ****************************************************************/
52 /*** file scope type declarations ****************************************************************/
54 /*** file scope variables ************************************************************************/
56 /*** file scope functions ************************************************************************/
57 /* --------------------------------------------------------------------------------------------- */
60 path_magic (const char *path
)
64 return (stat (path
, &buf
) != 0);
67 /* --------------------------------------------------------------------------------------------- */
70 * Splits path extracting vfs part.
73 * \verbatim /p1#op/inpath \endverbatim
75 * \verbatim inpath,op; \endverbatim
76 * returns which vfs it is.
77 * What is left in path is p1. You still want to g_free(path), you DON'T
78 * want to free neither *inpath nor *op
81 static struct vfs_class
*
82 _vfs_split_with_semi_skip_count (char *path
, const char **inpath
, const char **op
,
87 struct vfs_class
*ret
;
90 vfs_die ("Cannot split NULL");
92 semi
= strrstr_skip_count (path
, "#", skip_count
);
94 if ((semi
== NULL
) || (!path_magic (path
)))
97 slash
= strchr (semi
, PATH_SEP
);
109 ret
= vfs_prefix_to_class (semi
+ 1);
115 *inpath
= slash
!= NULL
? slash
+ 1 : NULL
;
123 ret
= _vfs_split_with_semi_skip_count (path
, inpath
, op
, skip_count
+ 1);
127 /* --------------------------------------------------------------------------------------------- */
129 * remove //, /./ and /../
131 * @return newly allocated string
135 vfs_canon (const char *path
)
138 vfs_die ("Cannot canonicalize NULL");
140 /* Relative to current directory */
141 if (*path
!= PATH_SEP
)
143 char *local
, *result
, *curr_dir
;
145 curr_dir
= vfs_get_current_dir ();
146 local
= concat_dir_and_file (curr_dir
, path
);
149 result
= vfs_canon (local
);
155 * So we have path of following form:
156 * /p1/p2#op/.././././p3#op/p4. Good luck.
159 char *result
= g_strdup (path
);
160 canonicalize_pathname (result
);
165 /* --------------------------------------------------------------------------------------------- */
167 * Build URL parameters (such as user:pass@host:port) from one path element object
169 * @param element path element
171 * @return newly allocated string
175 vfs_path_build_url_params_str (vfs_path_element_t
* element
)
182 buffer
= g_string_new ("");
184 if (element
->user
!= NULL
)
185 g_string_append (buffer
, element
->user
);
187 if (element
->password
!= NULL
)
189 g_string_append_c (buffer
, ':');
190 g_string_append (buffer
, element
->password
);
193 if (element
->host
!= NULL
)
195 if ((element
->user
!= NULL
) || (element
->password
!= NULL
))
196 g_string_append_c (buffer
, '@');
198 g_string_append_c (buffer
, '[');
199 g_string_append (buffer
, element
->host
);
201 g_string_append_c (buffer
, ']');
204 if ((element
->port
) != 0 && (element
->host
!= NULL
))
206 g_string_append_c (buffer
, ':');
207 g_string_append_printf (buffer
, "%d", element
->port
);
210 return g_string_free (buffer
, FALSE
);
213 /* --------------------------------------------------------------------------------------------- */
214 /** get encoding after last #enc: or NULL, if part does not contain #enc:
218 * @return newly allocated string.
222 vfs_get_encoding (const char *path
)
228 work
= g_strdup (path
);
230 /* try found #enc: */
231 semi
= g_strrstr (work
, VFS_ENCODING_PREFIX
);
233 if (semi
!= NULL
&& (semi
== work
|| *(semi
- 1) == PATH_SEP
))
235 semi
+= strlen (VFS_ENCODING_PREFIX
); /* skip "#enc:" */
236 slash
= strchr (semi
, PATH_SEP
);
240 g_strlcpy (result
, semi
, sizeof (result
));
242 return g_strdup (result
);
251 /* --------------------------------------------------------------------------------------------- */
252 /** Extract the hostname and username from the path
254 * Format of the path is [user@]hostname:port/remote-dir, e.g.:
256 * ftp://sunsite.unc.edu/pub/linux
257 * ftp://miguel@sphinx.nuclecu.unam.mx/c/nc
258 * ftp://tsx-11.mit.edu:8192/
259 * ftp://joe@foo.edu:11321/private
260 * ftp://joe:password@foo.se
262 * @param path_element is an input string to be parsed
263 * @param path is an input string to be parsed
265 * @return g_malloc()ed url info.
266 * If the user is empty, e.g. ftp://@roxanne/private, and URL_USE_ANONYMOUS
267 * is not set, then the current login name is supplied.
268 * Return value is a g_malloc()ed structure with the pathname relative to the
273 vfs_path_url_split (vfs_path_element_t
* path_element
, const char *path
)
277 char *dir
, *colon
, *inner_colon
, *at
, *rest
;
279 path_element
->port
= 0;
281 pcopy
= g_strdup (path
);
282 pend
= pcopy
+ strlen (pcopy
);
285 /* search for any possible user */
286 at
= strrchr (pcopy
, '@');
288 /* We have a username */
294 inner_colon
= strchr (pcopy
, ':');
295 if (inner_colon
!= NULL
)
299 path_element
->password
= g_strdup (inner_colon
);
303 path_element
->user
= g_strdup (pcopy
);
311 /* Check if the host comes with a port spec, if so, chop it */
313 colon
= strchr (rest
, ':');
316 colon
= strchr (++rest
, ']');
322 path_element
->ipv6
= TRUE
;
329 if (sscanf (colon
+ 1, "%d", &path_element
->port
) == 1)
331 if (path_element
->port
<= 0 || path_element
->port
>= 65536)
332 path_element
->port
= 0;
335 while (*(++colon
) != '\0')
340 path_element
->port
= 1;
343 path_element
->port
= 2;
348 path_element
->host
= g_strdup (rest
);
352 /* --------------------------------------------------------------------------------------------- */
354 * get VFS class for the given name
356 * @param class_name name of class
358 * @return pointer to class structure or NULL if class not found
361 static struct vfs_class
*
362 vfs_get_class_by_name (const char *class_name
)
366 if (class_name
== NULL
)
369 for (i
= 0; i
< vfs__classes_list
->len
; i
++)
371 struct vfs_class
*vfs
= (struct vfs_class
*) g_ptr_array_index (vfs__classes_list
, i
);
372 if ((vfs
->name
!= NULL
) && (strcmp (vfs
->name
, class_name
) == 0))
379 /* --------------------------------------------------------------------------------------------- */
381 * Check if path string contain URL-like elements
383 * @param path_str path
385 * @return TRUE if path is deprecated or FALSE otherwise
389 vfs_path_is_str_path_deprecated (const char *path_str
)
391 return strstr (path_str
, VFS_PATH_URL_DELIMITER
) == NULL
;
394 /* --------------------------------------------------------------------------------------------- */
395 /** Split path string to path elements by deprecated algorithm.
397 * @param path_str VFS-path
399 * @return pointer to newly created vfs_path_t object with filled path elements array.
403 vfs_path_from_str_deprecated_parser (char *path
)
406 vfs_path_element_t
*element
;
407 struct vfs_class
*class;
408 const char *local
, *op
;
410 vpath
= vfs_path_new ();
412 while ((class = _vfs_split_with_semi_skip_count (path
, &local
, &op
, 0)) != NULL
)
415 element
= g_new0 (vfs_path_element_t
, 1);
416 element
->class = class;
419 element
->path
= vfs_translate_path_n (local
);
421 element
->encoding
= vfs_get_encoding (local
);
422 element
->dir
.converter
=
423 (element
->encoding
!= NULL
) ? str_crt_conv_from (element
->encoding
) : INVALID_CONV
;
425 url_params
= strchr (op
, ':'); /* skip VFS prefix */
426 if (url_params
!= NULL
)
430 vfs_path_url_split (element
, url_params
);
434 element
->vfs_prefix
= g_strdup (op
);
436 vpath
->path
= g_list_prepend (vpath
->path
, element
);
440 element
= g_new0 (vfs_path_element_t
, 1);
441 element
->class = g_ptr_array_index (vfs__classes_list
, 0);
442 element
->path
= vfs_translate_path_n (path
);
444 element
->encoding
= vfs_get_encoding (path
);
445 element
->dir
.converter
=
446 (element
->encoding
!= NULL
) ? str_crt_conv_from (element
->encoding
) : INVALID_CONV
;
447 vpath
->path
= g_list_prepend (vpath
->path
, element
);
453 /* --------------------------------------------------------------------------------------------- */
454 /** Split path string to path elements by URL algorithm.
456 * @param path_str VFS-path
458 * @return pointer to newly created vfs_path_t object with filled path elements array.
462 vfs_path_from_str_uri_parser (char *path
)
465 vfs_path_element_t
*element
;
469 vpath
= vfs_path_new ();
471 while ((url_delimiter
= g_strrstr (path
, VFS_PATH_URL_DELIMITER
)) != NULL
)
473 char *vfs_prefix_start
;
474 char *real_vfs_prefix_start
= url_delimiter
;
476 struct vfs_s_subclass
*sub
= NULL
;
478 while (real_vfs_prefix_start
> path
&& *(real_vfs_prefix_start
) != PATH_SEP
)
479 real_vfs_prefix_start
--;
480 vfs_prefix_start
= real_vfs_prefix_start
;
482 if (*(vfs_prefix_start
) == PATH_SEP
)
483 vfs_prefix_start
+= 1;
485 *url_delimiter
= '\0';
487 element
= g_new0 (vfs_path_element_t
, 1);
488 element
->class = vfs_prefix_to_class (vfs_prefix_start
);
489 element
->vfs_prefix
= g_strdup (vfs_prefix_start
);
491 url_delimiter
+= strlen (VFS_PATH_URL_DELIMITER
);
492 sub
= VFSDATA (element
);
493 if (sub
!= NULL
&& sub
->flags
& VFS_S_REMOTE
)
495 slash_pointer
= strchr (url_delimiter
, PATH_SEP
);
496 if (slash_pointer
== NULL
)
498 element
->path
= g_strdup ("");
502 element
->path
= vfs_translate_path_n (slash_pointer
+ 1);
503 element
->encoding
= vfs_get_encoding (slash_pointer
);
505 *slash_pointer
= '\0';
507 vfs_path_url_split (element
, url_delimiter
);
511 element
->path
= vfs_translate_path_n (url_delimiter
);
512 element
->encoding
= vfs_get_encoding (url_delimiter
);
514 element
->dir
.converter
=
515 (element
->encoding
!= NULL
) ? str_crt_conv_from (element
->encoding
) : INVALID_CONV
;
516 vpath
->path
= g_list_prepend (vpath
->path
, element
);
518 if (real_vfs_prefix_start
> path
&& *(real_vfs_prefix_start
) == PATH_SEP
)
519 *real_vfs_prefix_start
= '\0';
521 *(real_vfs_prefix_start
+ 1) = '\0';
526 element
= g_new0 (vfs_path_element_t
, 1);
527 element
->class = g_ptr_array_index (vfs__classes_list
, 0);
528 element
->path
= vfs_translate_path_n (path
);
529 element
->encoding
= vfs_get_encoding (path
);
530 element
->dir
.converter
=
531 (element
->encoding
!= NULL
) ? str_crt_conv_from (element
->encoding
) : INVALID_CONV
;
532 vpath
->path
= g_list_prepend (vpath
->path
, element
);
538 /* --------------------------------------------------------------------------------------------- */
539 /*** public functions ****************************************************************************/
540 /* --------------------------------------------------------------------------------------------- */
542 * Convert first elements_count elements from vfs_path_t to string representation.
544 * @param vpath pointer to vfs_path_t object
545 * @param elements_count count of first elements for convert
546 * @param flags flags for parser
548 * @return pointer to newly created string.
551 #define vfs_append_from_path(appendfrom) \
553 if ((*appendfrom != PATH_SEP) && (*appendfrom != '\0') \
554 && (buffer->str[buffer->len - 1] != PATH_SEP)) \
555 g_string_append_c (buffer, PATH_SEP); \
556 g_string_append (buffer, appendfrom); \
560 vfs_path_to_str_elements_count (const vfs_path_t
* vpath
, int elements_count
)
564 GString
*recode_buffer
;
569 if (elements_count
> vfs_path_elements_count (vpath
))
570 elements_count
= vfs_path_elements_count (vpath
);
572 if (elements_count
< 0)
573 elements_count
= vfs_path_elements_count (vpath
) + elements_count
;
575 buffer
= g_string_new ("");
576 recode_buffer
= g_string_new ("");
578 for (element_index
= 0; element_index
< elements_count
; element_index
++)
580 vfs_path_element_t
*element
= vfs_path_get_by_index (vpath
, element_index
);
582 if (element
->vfs_prefix
!= NULL
)
586 if (buffer
->str
[buffer
->len
- 1] != '/')
587 g_string_append_c (buffer
, '/');
589 g_string_append (buffer
, element
->vfs_prefix
);
590 g_string_append (buffer
, VFS_PATH_URL_DELIMITER
);
592 url_str
= vfs_path_build_url_params_str (element
);
593 if (*url_str
!= '\0')
594 g_string_append (buffer
, url_str
);
599 if (vfs_path_element_need_cleanup_converter (element
))
601 if (buffer
->str
[buffer
->len
- 1] != PATH_SEP
)
602 g_string_append (buffer
, PATH_SEP_STR
);
603 g_string_append (buffer
, VFS_ENCODING_PREFIX
);
604 g_string_append (buffer
, element
->encoding
);
605 str_vfs_convert_from (element
->dir
.converter
, element
->path
, recode_buffer
);
606 vfs_append_from_path (recode_buffer
->str
);
607 g_string_set_size (recode_buffer
, 0);
611 vfs_append_from_path (element
->path
);
614 g_string_free (recode_buffer
, TRUE
);
615 return g_string_free (buffer
, FALSE
);
618 #undef vfs_append_from_path
620 /* --------------------------------------------------------------------------------------------- */
622 * Convert vfs_path_t to string representation.
624 * @param vpath pointer to vfs_path_t object
626 * @return pointer to newly created string.
630 vfs_path_to_str (const vfs_path_t
* vpath
)
632 return vfs_path_to_str_elements_count (vpath
, vfs_path_elements_count (vpath
));
635 /* --------------------------------------------------------------------------------------------- */
637 * Split path string to path elements with flags for change parce process.
639 * @param path_str VFS-path
640 * @param flags flags for parser
642 * @return pointer to newly created vfs_path_t object with filled path elements array.
646 vfs_path_from_str_flags (const char *path_str
, vfs_path_flag_t flags
)
651 if (path_str
== NULL
)
654 if ((flags
& VPF_NO_CANON
) == 0)
655 path
= vfs_canon (path_str
);
657 path
= g_strdup (path_str
);
662 if ((flags
& VPF_USE_DEPRECATED_PARSER
) != 0 && vfs_path_is_str_path_deprecated (path
))
663 vpath
= vfs_path_from_str_deprecated_parser (path
);
665 vpath
= vfs_path_from_str_uri_parser (path
);
672 /* --------------------------------------------------------------------------------------------- */
674 * Split path string to path elements.
676 * @param path_str VFS-path
678 * @return pointer to newly created vfs_path_t object with filled path elements array.
682 vfs_path_from_str (const char *path_str
)
684 return vfs_path_from_str_flags (path_str
, VPF_NONE
);
687 /* --------------------------------------------------------------------------------------------- */
689 * Create new vfs_path_t object.
691 * @return pointer to newly created vfs_path_t object.
698 vpath
= g_new0 (vfs_path_t
, 1);
702 /* --------------------------------------------------------------------------------------------- */
704 * Get count of path elements.
706 * @param vpath pointer to vfs_path_t object
708 * @return count of path elements.
712 vfs_path_elements_count (const vfs_path_t
* vpath
)
714 return (vpath
!= NULL
&& vpath
->path
!= NULL
) ? g_list_length (vpath
->path
) : 0;
717 /* --------------------------------------------------------------------------------------------- */
719 * Get one path element by index.
721 * @param vpath pointer to vfs_path_t object
722 * @param element_index element index. May have negative value (in this case count was started at the end of list).
724 * @return path element.
728 vfs_path_get_by_index (const vfs_path_t
* vpath
, int element_index
)
730 if (element_index
< 0)
731 element_index
+= vfs_path_elements_count (vpath
);
733 if (element_index
< 0)
734 vfs_die ("vfs_path_get_by_index: incorrect index!");
736 return g_list_nth_data (vpath
->path
, element_index
);
739 /* --------------------------------------------------------------------------------------------- */
741 * Clone one path element
743 * @param element pointer to vfs_path_element_t object
745 * @return Newly allocated path element
749 vfs_path_element_clone (const vfs_path_element_t
* element
)
751 vfs_path_element_t
*new_element
= g_new0 (vfs_path_element_t
, 1);
752 memcpy (new_element
, element
, sizeof (vfs_path_element_t
));
754 new_element
->user
= g_strdup (element
->user
);
755 new_element
->password
= g_strdup (element
->password
);
756 new_element
->host
= g_strdup (element
->host
);
757 new_element
->path
= g_strdup (element
->path
);
758 new_element
->encoding
= g_strdup (element
->encoding
);
759 if (vfs_path_element_need_cleanup_converter (element
) && new_element
->encoding
!= NULL
)
760 new_element
->dir
.converter
= str_crt_conv_from (new_element
->encoding
);
761 new_element
->vfs_prefix
= g_strdup (element
->vfs_prefix
);
766 /* --------------------------------------------------------------------------------------------- */
768 * Free one path element.
770 * @param element pointer to vfs_path_element_t object
775 vfs_path_element_free (vfs_path_element_t
* element
)
780 g_free (element
->user
);
781 g_free (element
->password
);
782 g_free (element
->host
);
783 g_free (element
->path
);
784 g_free (element
->encoding
);
785 g_free (element
->vfs_prefix
);
787 if (vfs_path_element_need_cleanup_converter (element
))
789 str_close_conv (element
->dir
.converter
);
795 /* --------------------------------------------------------------------------------------------- */
799 * @param vpath pointer to vfs_path_t object
801 * @return Newly allocated path object
805 vfs_path_clone (const vfs_path_t
* vpath
)
807 vfs_path_t
*new_vpath
;
808 int vpath_element_index
;
812 new_vpath
= vfs_path_new ();
813 for (vpath_element_index
= 0; vpath_element_index
< vfs_path_elements_count (vpath
);
814 vpath_element_index
++)
817 g_list_append (new_vpath
->path
,
818 vfs_path_element_clone (vfs_path_get_by_index
819 (vpath
, vpath_element_index
)));
825 /* --------------------------------------------------------------------------------------------- */
827 * Free vfs_path_t object.
829 * @param vpath pointer to vfs_path_t object
834 vfs_path_free (vfs_path_t
* path
)
838 g_list_foreach (path
->path
, (GFunc
) vfs_path_element_free
, NULL
);
839 g_list_free (path
->path
);
843 /* --------------------------------------------------------------------------------------------- */
845 * Remove one path element by index
847 * @param vpath pointer to vfs_path_t object
848 * @param element_index element index. May have negative value (in this case count was started at the end of list).
853 vfs_path_remove_element_by_index (vfs_path_t
* vpath
, int element_index
)
855 vfs_path_element_t
*element
;
857 if ((vpath
== NULL
) || (vfs_path_elements_count (vpath
) == 1))
860 if (element_index
< 0)
861 element_index
= vfs_path_elements_count (vpath
) + element_index
;
863 element
= g_list_nth_data (vpath
->path
, element_index
);
864 vpath
->path
= g_list_remove (vpath
->path
, element
);
865 vfs_path_element_free (element
);
868 /* --------------------------------------------------------------------------------------------- */
869 /** Return VFS class for the given prefix */
872 vfs_prefix_to_class (const char *prefix
)
876 /* Avoid first class (localfs) that would accept any prefix */
877 for (i
= 1; i
< vfs__classes_list
->len
; i
++)
879 struct vfs_class
*vfs
= (struct vfs_class
*) g_ptr_array_index (vfs__classes_list
, i
);
880 if (vfs
->which
!= NULL
)
882 if (vfs
->which (vfs
, prefix
) == -1)
887 if (vfs
->prefix
!= NULL
&& strncmp (prefix
, vfs
->prefix
, strlen (vfs
->prefix
)) == 0)
894 /* --------------------------------------------------------------------------------------------- */
896 * Check if need cleanup charset converter for vfs_path_element_t
898 * @param element part of path
900 * @return TRUE if need cleanup converter or FALSE otherwise
904 vfs_path_element_need_cleanup_converter (const vfs_path_element_t
* element
)
906 return (element
->dir
.converter
!= str_cnv_from_term
&& element
->dir
.converter
!= INVALID_CONV
);
909 /* --------------------------------------------------------------------------------------------- */
911 * Serialize vfs_path_t object to string
913 * @param vpath data for serialization
914 * @param error contain pointer to object for handle error code and message
916 * @return serialized vpath as newly allocated string
920 vfs_path_serialize (const vfs_path_t
* vpath
, GError
** error
)
922 mc_config_t
*cpath
= mc_config_init (NULL
);
923 ssize_t element_index
;
926 if ((vpath
== NULL
) || (vfs_path_elements_count (vpath
) == 0))
928 g_set_error (error
, MC_ERROR
, -1, "vpath object is empty");
932 for (element_index
= 0; element_index
< vfs_path_elements_count (vpath
); element_index
++)
934 char *groupname
= g_strdup_printf ("path-element-%zd", element_index
);
935 vfs_path_element_t
*element
= vfs_path_get_by_index (vpath
, element_index
);
937 /* convert one element to config group */
939 mc_config_set_string_raw (cpath
, groupname
, "path", element
->path
);
940 mc_config_set_string_raw (cpath
, groupname
, "class-name", element
->class->name
);
941 mc_config_set_string_raw (cpath
, groupname
, "encoding", element
->encoding
);
943 mc_config_set_string_raw (cpath
, groupname
, "vfs_prefix", element
->vfs_prefix
);
945 mc_config_set_string_raw (cpath
, groupname
, "user", element
->user
);
946 mc_config_set_string_raw (cpath
, groupname
, "password", element
->password
);
947 mc_config_set_string_raw (cpath
, groupname
, "host", element
->host
);
948 if (element
->port
!= 0)
949 mc_config_set_int (cpath
, groupname
, "port", element
->port
);
954 ret_value
= mc_serialize_config (cpath
, error
);
955 mc_config_deinit (cpath
);
959 /* --------------------------------------------------------------------------------------------- */
961 * Deserialize string to vfs_path_t object
963 * @param data data for serialization
964 * @param error contain pointer to object for handle error code and message
966 * @return newly allocated vfs_path_t object
970 vfs_path_deserialize (const char *data
, GError
** error
)
972 mc_config_t
*cpath
= mc_deserialize_config (data
, error
);
973 size_t element_index
= 0;
979 vpath
= vfs_path_new ();
983 vfs_path_element_t
*element
;
987 groupname
= g_strdup_printf ("path-element-%zd", element_index
);
988 if (!mc_config_has_group (cpath
, groupname
))
994 element
= g_new0 (vfs_path_element_t
, 1);
996 cfg_value
= mc_config_get_string_raw (cpath
, groupname
, "class-name", NULL
);
997 element
->class = vfs_get_class_by_name (cfg_value
);
998 if (element
->class == NULL
)
1001 vfs_path_free (vpath
);
1002 g_set_error (error
, MC_ERROR
, -1, "Unable to find VFS class by name '%s'", cfg_value
);
1004 mc_config_deinit (cpath
);
1009 element
->path
= mc_config_get_string_raw (cpath
, groupname
, "path", NULL
);
1010 element
->encoding
= mc_config_get_string_raw (cpath
, groupname
, "encoding", NULL
);
1011 element
->dir
.converter
=
1012 (element
->encoding
!= NULL
) ? str_crt_conv_from (element
->encoding
) : INVALID_CONV
;
1014 element
->vfs_prefix
= mc_config_get_string_raw (cpath
, groupname
, "vfs_prefix", NULL
);
1016 element
->user
= mc_config_get_string_raw (cpath
, groupname
, "user", NULL
);
1017 element
->password
= mc_config_get_string_raw (cpath
, groupname
, "password", NULL
);
1018 element
->host
= mc_config_get_string_raw (cpath
, groupname
, "host", NULL
);
1019 element
->port
= mc_config_get_int (cpath
, groupname
, "port", 0);
1021 vpath
->path
= g_list_append (vpath
->path
, element
);
1027 mc_config_deinit (cpath
);
1028 if (vfs_path_elements_count (vpath
) == 0)
1030 vfs_path_free (vpath
);
1031 g_set_error (error
, MC_ERROR
, -1, "No any path elements found");
1038 /* --------------------------------------------------------------------------------------------- */