2011-10-15 14:56:47 +04:00
|
|
|
/*
|
|
|
|
Virtual File System switch code
|
|
|
|
|
2024-01-01 09:46:17 +03:00
|
|
|
Copyright (C) 1995-2024
|
2014-02-12 10:33:10 +04:00
|
|
|
Free Software Foundation, Inc.
|
2010-03-30 12:10:25 +04:00
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
Written by: 1995 Miguel de Icaza
|
2011-10-15 14:56:47 +04:00
|
|
|
Jakub Jelinek, 1995
|
|
|
|
Pavel Machek, 1998
|
2022-05-07 10:15:14 +03:00
|
|
|
Slava Zanko <slavazanko@gmail.com>, 2011-2013
|
|
|
|
Andrew Borodin <aborodin@vmail.ru>, 2011-2022
|
2011-10-15 14:56:47 +04:00
|
|
|
|
|
|
|
This file is part of the Midnight Commander.
|
2010-03-30 12:10:25 +04:00
|
|
|
|
2011-10-15 14:56:47 +04:00
|
|
|
The Midnight Commander is free software: you can redistribute it
|
|
|
|
and/or modify it under the terms of the GNU General Public License as
|
|
|
|
published by the Free Software Foundation, either version 3 of the License,
|
|
|
|
or (at your option) any later version.
|
2010-03-30 12:10:25 +04:00
|
|
|
|
2011-10-15 14:56:47 +04:00
|
|
|
The Midnight Commander is distributed in the hope that it will be useful,
|
1998-02-27 07:54:42 +03:00
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2011-10-15 14:56:47 +04:00
|
|
|
GNU General Public License for more details.
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2011-10-15 14:56:47 +04:00
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2009-02-07 15:54:58 +03:00
|
|
|
/**
|
|
|
|
* \file
|
|
|
|
* \brief Source: Virtual File System switch code
|
|
|
|
* \author Miguel de Icaza
|
|
|
|
* \author Jakub Jelinek
|
|
|
|
* \author Pavel Machek
|
|
|
|
* \date 1995, 1998
|
2014-08-13 01:02:58 +04:00
|
|
|
* \warning functions like extfs_lstat() have right to destroy any
|
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
|
|
|
* strings you pass to them. This is actually ok as you g_strdup what
|
2009-02-07 15:54:58 +03:00
|
|
|
* you are passing to them, anyway; still, beware.
|
|
|
|
*
|
|
|
|
* Namespace: exports *many* functions with vfs_ prefix; exports
|
|
|
|
* parse_ls_lga and friends which do not have that prefix.
|
|
|
|
*/
|
1998-10-13 02:07:53 +04:00
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
#include <config.h>
|
1998-10-14 06:56:18 +04:00
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
#include <errno.h>
|
2013-12-02 14:38:43 +04:00
|
|
|
#include <stdlib.h>
|
1999-01-21 01:01:11 +03:00
|
|
|
|
2018-08-11 20:48:51 +03:00
|
|
|
#ifdef __linux__
|
2018-08-11 21:00:42 +03:00
|
|
|
#ifdef HAVE_LINUX_FS_H
|
2018-08-11 20:48:51 +03:00
|
|
|
#include <linux/fs.h>
|
2018-08-11 21:00:42 +03:00
|
|
|
#endif /* HAVE_LINUX_FS_H */
|
2018-08-11 20:48:51 +03:00
|
|
|
#ifdef HAVE_SYS_IOCTL_H
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#endif /* HAVE_SYS_IOCTL_H */
|
|
|
|
#endif /* __linux__ */
|
|
|
|
|
2010-01-20 18:11:52 +03:00
|
|
|
#include "lib/global.h"
|
2010-01-21 15:17:26 +03:00
|
|
|
#include "lib/strutil.h"
|
2010-11-11 16:58:29 +03:00
|
|
|
#include "lib/util.h"
|
2010-11-12 11:03:57 +03:00
|
|
|
#include "lib/widget.h" /* message() */
|
2011-02-16 14:26:59 +03:00
|
|
|
#include "lib/event.h"
|
2010-07-22 12:07:07 +04:00
|
|
|
|
2010-05-19 10:30:37 +04:00
|
|
|
#ifdef HAVE_CHARSET
|
2010-11-18 11:31:09 +03:00
|
|
|
#include "lib/charsets.h"
|
2010-05-19 10:30:37 +04:00
|
|
|
#endif
|
2009-05-08 14:01:05 +04:00
|
|
|
|
2011-02-15 16:44:17 +03:00
|
|
|
#include "vfs.h"
|
1999-01-21 01:01:11 +03:00
|
|
|
#include "utilvfs.h"
|
2003-11-08 02:43:55 +03:00
|
|
|
#include "gc.h"
|
2010-07-22 12:07:07 +04:00
|
|
|
|
2015-05-10 17:55:54 +03:00
|
|
|
/* TODO: move it to the separate .h */
|
2020-11-16 10:09:09 +03:00
|
|
|
extern struct vfs_dirent *mc_readdir_result;
|
2015-05-10 17:55:54 +03:00
|
|
|
extern GPtrArray *vfs__classes_list;
|
|
|
|
extern GString *vfs_str_buffer;
|
2016-03-03 22:51:40 +03:00
|
|
|
extern vfs_class *current_vfs;
|
2015-05-10 17:55:54 +03:00
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/*** global variables ****************************************************************************/
|
|
|
|
|
2020-11-16 10:09:09 +03:00
|
|
|
struct vfs_dirent *mc_readdir_result = NULL;
|
2011-04-28 15:39:59 +04:00
|
|
|
GPtrArray *vfs__classes_list = NULL;
|
2011-04-29 15:13:29 +04:00
|
|
|
GString *vfs_str_buffer = NULL;
|
2016-03-03 22:51:40 +03:00
|
|
|
vfs_class *current_vfs = NULL;
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/*** file scope macro definitions ****************************************************************/
|
|
|
|
|
|
|
|
#define VFS_FIRST_HANDLE 100
|
|
|
|
|
|
|
|
/*** file scope type declarations ****************************************************************/
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2010-03-30 12:10:25 +04:00
|
|
|
struct vfs_openfile
|
|
|
|
{
|
2003-11-05 03:12:25 +03:00
|
|
|
int handle;
|
2016-03-03 22:51:40 +03:00
|
|
|
vfs_class *vclass;
|
2003-11-05 03:12:25 +03:00
|
|
|
void *fsinfo;
|
|
|
|
};
|
1998-10-14 06:56:18 +04:00
|
|
|
|
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) *************************************************/
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/*** file scope variables ************************************************************************/
|
|
|
|
|
2011-04-29 15:13:29 +04:00
|
|
|
/** They keep track of the current directory */
|
|
|
|
static vfs_path_t *current_path = NULL;
|
2008-12-29 02:54:37 +03:00
|
|
|
|
2016-11-12 18:58:05 +03:00
|
|
|
static GPtrArray *vfs_openfiles = NULL;
|
2009-05-14 18:52:10 +04:00
|
|
|
static long vfs_free_handle_list = -1;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2012-04-30 14:58:25 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2010-11-08 13:21:45 +03:00
|
|
|
/*** file scope functions ************************************************************************/
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/* now used only by vfs_translate_path, but could be used in other vfs
|
|
|
|
* plugin to automatic detect encoding
|
|
|
|
* path - path to translate
|
|
|
|
* size - how many bytes from path translate
|
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
|
|
|
* defcnv - converter, that is used as default, when path does not contain any
|
|
|
|
* #enc: substring
|
2010-11-08 13:21:45 +03:00
|
|
|
* buffer - used to store result of translation
|
|
|
|
*/
|
|
|
|
|
|
|
|
static estr_t
|
2024-06-01 21:12:14 +03:00
|
|
|
_vfs_translate_path (const char *path, int size, GIConv defcnv, GString *buffer)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2012-04-30 14:58:25 +04:00
|
|
|
estr_t state = ESTR_SUCCESS;
|
|
|
|
#ifdef HAVE_CHARSET
|
2010-11-08 13:21:45 +03:00
|
|
|
const char *semi;
|
|
|
|
|
|
|
|
if (size == 0)
|
|
|
|
return ESTR_SUCCESS;
|
|
|
|
|
|
|
|
size = (size > 0) ? size : (signed int) strlen (path);
|
|
|
|
|
|
|
|
/* try found /#enc: */
|
2011-05-30 17:54:45 +04:00
|
|
|
semi = g_strrstr_len (path, size, VFS_ENCODING_PREFIX);
|
2015-01-07 11:34:53 +03:00
|
|
|
if (semi != NULL && (semi == path || IS_PATH_SEP (semi[-1])))
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
|
|
|
char encoding[16];
|
2013-10-15 10:34:04 +04:00
|
|
|
const char *slash;
|
2010-11-08 13:21:45 +03:00
|
|
|
GIConv coder = INVALID_CONV;
|
|
|
|
int ms;
|
|
|
|
|
2011-06-02 14:20:14 +04:00
|
|
|
/* first must be translated part before #enc: */
|
2010-11-08 13:21:45 +03:00
|
|
|
ms = semi - path;
|
|
|
|
|
|
|
|
state = _vfs_translate_path (path, ms, defcnv, buffer);
|
|
|
|
|
|
|
|
if (state != ESTR_SUCCESS)
|
|
|
|
return state;
|
|
|
|
|
|
|
|
/* now can be translated part after #enc: */
|
2011-06-02 14:20:14 +04:00
|
|
|
semi += strlen (VFS_ENCODING_PREFIX); /* skip "#enc:" */
|
2010-11-08 13:21:45 +03:00
|
|
|
slash = strchr (semi, PATH_SEP);
|
|
|
|
/* ignore slashes after size; */
|
|
|
|
if (slash - path >= size)
|
|
|
|
slash = NULL;
|
|
|
|
|
|
|
|
ms = (slash != NULL) ? slash - semi : (int) strlen (semi);
|
2016-04-07 10:52:04 +03:00
|
|
|
ms = MIN ((unsigned int) ms, sizeof (encoding) - 1);
|
2010-11-08 13:21:45 +03:00
|
|
|
/* limit encoding size (ms) to path size (size) */
|
|
|
|
if (semi + ms > path + size)
|
|
|
|
ms = path + size - semi;
|
|
|
|
memcpy (encoding, semi, ms);
|
|
|
|
encoding[ms] = '\0';
|
|
|
|
|
|
|
|
if (is_supported_encoding (encoding))
|
|
|
|
coder = str_crt_conv_to (encoding);
|
|
|
|
|
|
|
|
if (coder != INVALID_CONV)
|
|
|
|
{
|
|
|
|
if (slash != NULL)
|
2011-05-30 17:54:45 +04:00
|
|
|
state = str_vfs_convert_to (coder, slash + 1, path + size - slash - 1, buffer);
|
2010-11-08 13:21:45 +03:00
|
|
|
str_close_conv (coder);
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
errno = EINVAL;
|
|
|
|
state = ESTR_FAILURE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* path can be translated whole at once */
|
|
|
|
state = str_vfs_convert_to (defcnv, path, size, buffer);
|
|
|
|
}
|
2012-04-30 14:58:25 +04:00
|
|
|
#else
|
|
|
|
(void) size;
|
|
|
|
(void) defcnv;
|
|
|
|
|
|
|
|
g_string_assign (buffer, path);
|
2012-07-06 14:56:29 +04:00
|
|
|
#endif /* HAVE_CHARSET */
|
2010-11-08 13:21:45 +03:00
|
|
|
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
2011-09-21 14:44:03 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
static struct vfs_openfile *
|
|
|
|
vfs_get_openfile (int handle)
|
|
|
|
{
|
|
|
|
struct vfs_openfile *h;
|
|
|
|
|
|
|
|
if (handle < VFS_FIRST_HANDLE || (guint) (handle - VFS_FIRST_HANDLE) >= vfs_openfiles->len)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
h = (struct vfs_openfile *) g_ptr_array_index (vfs_openfiles, handle - VFS_FIRST_HANDLE);
|
|
|
|
if (h == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
g_assert (h->handle == handle);
|
|
|
|
|
|
|
|
return h;
|
|
|
|
}
|
|
|
|
|
2016-06-30 11:01:47 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
static gboolean
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_test_current_dir (const vfs_path_t *vpath)
|
2016-06-30 11:01:47 +03:00
|
|
|
{
|
|
|
|
struct stat my_stat, my_stat2;
|
|
|
|
|
|
|
|
return (mc_global.vfs.cd_symlinks && mc_stat (vpath, &my_stat) == 0
|
|
|
|
&& mc_stat (vfs_get_raw_current_dir (), &my_stat2) == 0
|
|
|
|
&& my_stat.st_ino == my_stat2.st_ino && my_stat.st_dev == my_stat2.st_dev);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2011-04-07 16:27:46 +04:00
|
|
|
/*** public functions ****************************************************************************/
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/** Free open file data for given file handle */
|
2010-11-08 13:21:45 +03:00
|
|
|
|
2011-04-07 16:27:46 +04:00
|
|
|
void
|
|
|
|
vfs_free_handle (int handle)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2011-04-07 16:27:46 +04:00
|
|
|
const int idx = handle - VFS_FIRST_HANDLE;
|
|
|
|
|
|
|
|
if (handle >= VFS_FIRST_HANDLE && (guint) idx < vfs_openfiles->len)
|
|
|
|
{
|
|
|
|
struct vfs_openfile *h;
|
|
|
|
|
|
|
|
h = (struct vfs_openfile *) g_ptr_array_index (vfs_openfiles, idx);
|
|
|
|
g_free (h);
|
|
|
|
g_ptr_array_index (vfs_openfiles, idx) = (void *) vfs_free_handle_list;
|
|
|
|
vfs_free_handle_list = idx;
|
|
|
|
}
|
2010-11-08 13:21:45 +03:00
|
|
|
}
|
|
|
|
|
2011-04-07 16:27:46 +04:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/** Find VFS class by file handle */
|
2010-11-08 13:21:45 +03:00
|
|
|
|
2011-04-07 16:27:46 +04:00
|
|
|
struct vfs_class *
|
2016-03-24 11:00:56 +03:00
|
|
|
vfs_class_find_by_handle (int handle, void **fsinfo)
|
2011-04-07 16:27:46 +04:00
|
|
|
{
|
|
|
|
struct vfs_openfile *h;
|
2010-11-08 13:21:45 +03:00
|
|
|
|
2011-09-21 14:44:03 +04:00
|
|
|
h = vfs_get_openfile (handle);
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2016-03-24 11:00:56 +03:00
|
|
|
if (h == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (fsinfo != NULL)
|
|
|
|
*fsinfo = h->fsinfo;
|
|
|
|
|
|
|
|
return h->vclass;
|
2010-11-08 13:21:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2011-04-07 16:27:46 +04:00
|
|
|
/**
|
|
|
|
* Create new VFS handle and put it to the list
|
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
|
|
|
vfs_new_handle (struct vfs_class *vclass, void *fsinfo)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2011-04-07 16:27:46 +04:00
|
|
|
struct vfs_openfile *h;
|
2010-11-08 13:21:45 +03:00
|
|
|
|
2011-04-07 16:27:46 +04:00
|
|
|
h = g_new (struct vfs_openfile, 1);
|
|
|
|
h->fsinfo = fsinfo;
|
|
|
|
h->vclass = vclass;
|
2010-11-08 13:21:45 +03:00
|
|
|
|
2011-04-07 16:27:46 +04:00
|
|
|
/* Allocate the first free handle */
|
|
|
|
h->handle = vfs_free_handle_list;
|
|
|
|
if (h->handle == -1)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2011-04-07 16:27:46 +04:00
|
|
|
/* No free allocated handles, allocate one */
|
|
|
|
h->handle = vfs_openfiles->len;
|
|
|
|
g_ptr_array_add (vfs_openfiles, h);
|
2010-11-08 13:21:45 +03:00
|
|
|
}
|
2011-04-07 16:27:46 +04:00
|
|
|
else
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2011-04-07 16:27:46 +04:00
|
|
|
vfs_free_handle_list = (long) g_ptr_array_index (vfs_openfiles, vfs_free_handle_list);
|
|
|
|
g_ptr_array_index (vfs_openfiles, h->handle) = h;
|
2010-11-08 13:21:45 +03:00
|
|
|
}
|
|
|
|
|
2011-04-07 16:27:46 +04:00
|
|
|
h->handle += VFS_FIRST_HANDLE;
|
|
|
|
return h->handle;
|
2010-11-08 13:21:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2011-04-07 16:27:46 +04:00
|
|
|
int
|
|
|
|
vfs_ferrno (struct vfs_class *vfs)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2011-04-07 16:27:46 +04:00
|
|
|
return vfs->ferrno ? (*vfs->ferrno) (vfs) : E_UNKNOWN;
|
|
|
|
/* Hope that error message is obscure enough ;-) */
|
2010-11-08 13:21:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2011-02-15 16:44:17 +03:00
|
|
|
gboolean
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_register_class (struct vfs_class *vfs)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
|
|
|
if (vfs->init != NULL) /* vfs has own initialization function */
|
2011-02-15 16:44:17 +03:00
|
|
|
if (!vfs->init (vfs)) /* but it failed */
|
|
|
|
return FALSE;
|
2010-11-08 13:21:45 +03:00
|
|
|
|
2011-04-28 15:39:59 +04:00
|
|
|
g_ptr_array_add (vfs__classes_list, vfs);
|
2010-11-08 13:21:45 +03:00
|
|
|
|
2011-02-15 16:44:17 +03:00
|
|
|
return TRUE;
|
2010-11-08 13:21:45 +03:00
|
|
|
}
|
|
|
|
|
2018-09-14 09:17:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
void
|
|
|
|
vfs_unregister_class (struct vfs_class *vfs)
|
|
|
|
{
|
|
|
|
if (vfs->done != NULL)
|
|
|
|
vfs->done (vfs);
|
|
|
|
|
|
|
|
g_ptr_array_remove (vfs__classes_list, vfs);
|
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2009-02-07 15:54:58 +03:00
|
|
|
/** Strip known vfs suffixes from a filename (possible improvement: strip
|
|
|
|
* suffix from last path component).
|
|
|
|
* \return a malloced string which has to be freed.
|
|
|
|
*/
|
2010-11-08 13:21:45 +03:00
|
|
|
|
1998-12-16 09:16:13 +03:00
|
|
|
char *
|
2001-03-05 09:00:27 +03:00
|
|
|
vfs_strip_suffix_from_filename (const char *filename)
|
1998-12-16 09:16:13 +03:00
|
|
|
{
|
2016-07-07 15:34:36 +03:00
|
|
|
char *semi, *p;
|
1998-12-16 09:16:13 +03:00
|
|
|
|
2010-03-30 22:59:41 +04:00
|
|
|
if (filename == NULL)
|
2010-03-30 12:10:25 +04:00
|
|
|
vfs_die ("vfs_strip_suffix_from_path got NULL: impossible");
|
2003-09-29 00:35:08 +04:00
|
|
|
|
2009-02-06 01:40:32 +03:00
|
|
|
p = g_strdup (filename);
|
2011-06-14 16:09:59 +04:00
|
|
|
semi = g_strrstr (p, VFS_PATH_URL_DELIMITER);
|
2016-07-07 15:34:36 +03:00
|
|
|
if (semi != NULL)
|
2010-03-30 12:10:25 +04:00
|
|
|
{
|
2016-07-07 15:34:36 +03:00
|
|
|
char *vfs_prefix;
|
|
|
|
|
|
|
|
*semi = '\0';
|
|
|
|
vfs_prefix = strrchr (p, PATH_SEP);
|
|
|
|
if (vfs_prefix == NULL)
|
|
|
|
*semi = *VFS_PATH_URL_DELIMITER;
|
|
|
|
else
|
|
|
|
*vfs_prefix = '\0';
|
1998-12-16 09:16:13 +03:00
|
|
|
}
|
2011-06-14 16:09:59 +04:00
|
|
|
|
1998-12-16 09:16:13 +03:00
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
1998-08-25 20:00:16 +04:00
|
|
|
|
2013-09-17 12:47:10 +04:00
|
|
|
const char *
|
2010-03-30 12:10:25 +04:00
|
|
|
vfs_translate_path (const char *path)
|
2008-12-29 02:54:37 +03:00
|
|
|
{
|
2009-04-22 20:35:32 +04:00
|
|
|
estr_t state;
|
|
|
|
|
2010-03-30 12:10:25 +04:00
|
|
|
g_string_set_size (vfs_str_buffer, 0);
|
2008-12-29 02:54:37 +03:00
|
|
|
state = _vfs_translate_path (path, -1, str_cnv_from_term, vfs_str_buffer);
|
2009-04-14 14:29:01 +04:00
|
|
|
return (state != ESTR_FAILURE) ? vfs_str_buffer->str : NULL;
|
2008-12-29 02:54:37 +03:00
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2008-12-29 02:54:37 +03:00
|
|
|
char *
|
2010-03-30 12:10:25 +04:00
|
|
|
vfs_translate_path_n (const char *path)
|
2008-12-29 02:54:37 +03:00
|
|
|
{
|
2013-09-17 12:47:10 +04:00
|
|
|
const char *result;
|
2009-08-03 19:37:55 +04:00
|
|
|
|
2008-12-29 02:54:37 +03:00
|
|
|
result = vfs_translate_path (path);
|
2013-09-17 12:48:11 +04:00
|
|
|
return g_strdup (result);
|
2008-12-29 02:54:37 +03:00
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2011-04-07 16:27:46 +04:00
|
|
|
/**
|
2011-04-29 15:13:29 +04:00
|
|
|
* Get current directory without any OS calls.
|
|
|
|
*
|
2015-10-18 08:07:08 +03:00
|
|
|
* @return string contains current path
|
2011-04-07 16:27:46 +04:00
|
|
|
*/
|
|
|
|
|
2015-10-18 08:07:08 +03:00
|
|
|
const char *
|
2011-04-07 16:27:46 +04:00
|
|
|
vfs_get_current_dir (void)
|
2015-10-18 08:07:08 +03:00
|
|
|
{
|
|
|
|
return current_path->str;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* Get current directory without any OS calls.
|
|
|
|
*
|
|
|
|
* @return newly allocated string contains current path
|
|
|
|
*/
|
|
|
|
|
|
|
|
char *
|
|
|
|
vfs_get_current_dir_n (void)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2013-04-14 17:38:37 +04:00
|
|
|
return g_strdup (current_path->str);
|
2011-04-29 15:13:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* Get raw current directory object without any OS calls.
|
|
|
|
*
|
|
|
|
* @return object contain current path
|
|
|
|
*/
|
|
|
|
|
2012-03-23 15:38:36 +04:00
|
|
|
const vfs_path_t *
|
2011-04-29 15:13:29 +04:00
|
|
|
vfs_get_raw_current_dir (void)
|
|
|
|
{
|
|
|
|
return current_path;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* Set current directory object.
|
|
|
|
*
|
|
|
|
* @param vpath new path
|
|
|
|
*/
|
|
|
|
void
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_set_raw_current_dir (const vfs_path_t *vpath)
|
2011-04-29 15:13:29 +04:00
|
|
|
{
|
2021-02-21 19:30:18 +03:00
|
|
|
vfs_path_free (current_path, TRUE);
|
2011-04-29 15:13:29 +04:00
|
|
|
current_path = (vfs_path_t *) vpath;
|
2011-04-07 16:27:46 +04:00
|
|
|
}
|
2000-02-24 15:00:30 +03:00
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2011-04-07 16:27:46 +04:00
|
|
|
/* Return TRUE is the current VFS class is local */
|
2010-11-08 13:21:45 +03:00
|
|
|
|
2010-07-08 14:24:58 +04:00
|
|
|
gboolean
|
1998-10-14 06:56:18 +04:00
|
|
|
vfs_current_is_local (void)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2019-11-18 21:24:13 +03:00
|
|
|
return (current_vfs->flags & VFSF_LOCAL) != 0;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2003-10-11 12:21:16 +04:00
|
|
|
/* Return flags of the VFS class of the given filename */
|
2010-11-08 13:21:45 +03:00
|
|
|
|
2018-09-11 14:54:28 +03:00
|
|
|
vfs_flags_t
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_file_class_flags (const vfs_path_t *vpath)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2012-01-03 13:35:57 +04:00
|
|
|
const vfs_path_element_t *path_element;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2012-01-03 13:35:57 +04:00
|
|
|
path_element = vfs_path_get_by_index (vpath, -1);
|
2011-06-17 14:28:37 +04:00
|
|
|
if (!vfs_path_element_valid (path_element))
|
2019-11-18 21:24:13 +03:00
|
|
|
return VFSF_UNKNOWN;
|
2010-03-31 13:07:39 +04:00
|
|
|
|
2011-05-01 13:16:46 +04:00
|
|
|
return path_element->class->flags;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
1998-02-27 07:54:42 +03:00
|
|
|
|
1998-10-14 06:56:18 +04:00
|
|
|
void
|
|
|
|
vfs_init (void)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2011-02-15 16:44:17 +03:00
|
|
|
/* create the VFS handle arrays */
|
2011-04-28 15:39:59 +04:00
|
|
|
vfs__classes_list = g_ptr_array_new ();
|
2011-02-15 16:44:17 +03:00
|
|
|
|
2009-05-14 18:52:10 +04:00
|
|
|
/* create the VFS handle array */
|
|
|
|
vfs_openfiles = g_ptr_array_new ();
|
|
|
|
|
2010-03-30 12:10:25 +04:00
|
|
|
vfs_str_buffer = g_string_new ("");
|
2003-10-13 02:25:53 +04:00
|
|
|
|
2020-11-16 10:09:09 +03:00
|
|
|
mc_readdir_result = vfs_dirent_init (NULL, "", -1);
|
2011-02-15 16:44:17 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
1998-09-27 23:27:58 +04:00
|
|
|
|
2011-02-15 16:44:17 +03:00
|
|
|
void
|
|
|
|
vfs_setup_work_dir (void)
|
|
|
|
{
|
2011-09-27 23:13:50 +04:00
|
|
|
vfs_setup_cwd ();
|
2011-02-15 16:44:17 +03:00
|
|
|
|
2011-04-29 15:13:29 +04:00
|
|
|
/* FIXME: is we really need for this check? */
|
|
|
|
/*
|
|
|
|
if (strlen (current_dir) > MC_MAXPATHLEN - 2)
|
|
|
|
vfs_die ("Current dir too long.\n");
|
|
|
|
*/
|
2011-02-15 16:44:17 +03:00
|
|
|
|
2023-07-16 11:18:59 +03:00
|
|
|
current_vfs = VFS_CLASS (vfs_path_get_last_path_vfs (current_path));
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
1998-10-14 06:56:18 +04:00
|
|
|
void
|
|
|
|
vfs_shut (void)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2011-02-15 16:44:17 +03:00
|
|
|
guint i;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2003-11-08 02:43:55 +03:00
|
|
|
vfs_gc_done ();
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2011-04-29 15:13:29 +04:00
|
|
|
vfs_set_raw_current_dir (NULL);
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2011-04-28 15:39:59 +04:00
|
|
|
for (i = 0; i < vfs__classes_list->len; i++)
|
2011-02-15 16:44:17 +03:00
|
|
|
{
|
2018-09-12 14:01:28 +03:00
|
|
|
struct vfs_class *vfs = VFS_CLASS (g_ptr_array_index (vfs__classes_list, i));
|
2011-02-15 16:44:17 +03:00
|
|
|
|
|
|
|
if (vfs->done != NULL)
|
|
|
|
vfs->done (vfs);
|
|
|
|
}
|
2003-11-05 03:12:25 +03:00
|
|
|
|
2016-11-12 18:58:05 +03:00
|
|
|
/* NULL-ize pointers to make unit tests happy */
|
2009-05-14 18:52:10 +04:00
|
|
|
g_ptr_array_free (vfs_openfiles, TRUE);
|
2016-11-12 18:58:05 +03:00
|
|
|
vfs_openfiles = NULL;
|
2011-04-28 15:39:59 +04:00
|
|
|
g_ptr_array_free (vfs__classes_list, TRUE);
|
2016-11-12 18:58:05 +03:00
|
|
|
vfs__classes_list = NULL;
|
2009-04-14 14:29:01 +04:00
|
|
|
g_string_free (vfs_str_buffer, TRUE);
|
2016-11-12 18:58:05 +03:00
|
|
|
vfs_str_buffer = NULL;
|
|
|
|
current_vfs = NULL;
|
|
|
|
vfs_free_handle_list = -1;
|
2020-11-16 10:09:09 +03:00
|
|
|
vfs_dirent_free (mc_readdir_result);
|
|
|
|
mc_readdir_result = NULL;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2020-11-16 10:09:09 +03:00
|
|
|
/**
|
|
|
|
* Init or create vfs_dirent structure
|
|
|
|
*
|
|
|
|
* @d vfs_dirent structure to init. If NULL, new structure is created.
|
|
|
|
* @fname file name
|
|
|
|
* @ino file inode number
|
|
|
|
*
|
|
|
|
* @return pointer to d if d isn't NULL, or pointer to newly created structure.
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct vfs_dirent *
|
|
|
|
vfs_dirent_init (struct vfs_dirent *d, const char *fname, ino_t ino)
|
|
|
|
{
|
|
|
|
struct vfs_dirent *ret = d;
|
|
|
|
|
|
|
|
if (ret == NULL)
|
|
|
|
ret = g_new0 (struct vfs_dirent, 1);
|
|
|
|
|
|
|
|
if (ret->d_name_str == NULL)
|
|
|
|
ret->d_name_str = g_string_sized_new (MC_MAXFILENAMELEN);
|
|
|
|
|
|
|
|
vfs_dirent_assign (ret, fname, ino);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* Assign members of vfs_dirent structure
|
|
|
|
*
|
|
|
|
* @d vfs_dirent structure for assignment
|
|
|
|
* @fname file name
|
|
|
|
* @ino file inode number
|
|
|
|
*/
|
|
|
|
|
|
|
|
void
|
|
|
|
vfs_dirent_assign (struct vfs_dirent *d, const char *fname, ino_t ino)
|
|
|
|
{
|
|
|
|
g_string_assign (d->d_name_str, fname);
|
|
|
|
d->d_name = d->d_name_str->str;
|
2024-05-01 10:30:57 +03:00
|
|
|
d->d_len = d->d_name_str->len;
|
2020-11-16 10:09:09 +03:00
|
|
|
d->d_ino = ino;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* Destroy vfs_dirent structure
|
|
|
|
*
|
|
|
|
* @d vfs_dirent structure to destroy.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void
|
|
|
|
vfs_dirent_free (struct vfs_dirent *d)
|
|
|
|
{
|
|
|
|
g_string_free (d->d_name_str, TRUE);
|
|
|
|
g_free (d);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/**
|
1998-10-14 06:56:18 +04:00
|
|
|
* These ones grab information from the VFS
|
1998-02-27 07:54:42 +03:00
|
|
|
* and handles them to an upper layer
|
|
|
|
*/
|
2010-11-08 13:21:45 +03:00
|
|
|
|
1998-10-14 06:56:18 +04:00
|
|
|
void
|
2004-08-16 20:34:11 +04:00
|
|
|
vfs_fill_names (fill_names_f func)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2011-02-15 16:44:17 +03:00
|
|
|
guint i;
|
1998-10-14 06:56:18 +04:00
|
|
|
|
2011-04-28 15:39:59 +04:00
|
|
|
for (i = 0; i < vfs__classes_list->len; i++)
|
2011-02-15 16:44:17 +03:00
|
|
|
{
|
2018-09-12 14:01:28 +03:00
|
|
|
struct vfs_class *vfs = VFS_CLASS (g_ptr_array_index (vfs__classes_list, i));
|
2011-02-15 16:44:17 +03:00
|
|
|
|
|
|
|
if (vfs->fill_names != NULL)
|
|
|
|
vfs->fill_names (vfs, func);
|
|
|
|
}
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2018-09-11 14:54:28 +03:00
|
|
|
|
2010-07-08 14:24:58 +04:00
|
|
|
gboolean
|
2024-06-01 21:12:14 +03:00
|
|
|
vfs_file_is_local (const vfs_path_t *vpath)
|
2004-08-17 03:25:49 +04:00
|
|
|
{
|
2019-11-18 21:24:13 +03:00
|
|
|
return (vfs_file_class_flags (vpath) & VFSF_LOCAL) != 0;
|
2004-08-17 03:25:49 +04:00
|
|
|
}
|
2010-11-08 13:21:45 +03:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2011-02-16 14:26:59 +03:00
|
|
|
|
|
|
|
void
|
|
|
|
vfs_print_message (const char *msg, ...)
|
|
|
|
{
|
|
|
|
ev_vfs_print_message_t event_data;
|
2015-11-04 13:08:33 +03:00
|
|
|
va_list ap;
|
2011-02-16 14:26:59 +03:00
|
|
|
|
2015-11-04 13:08:33 +03:00
|
|
|
va_start (ap, msg);
|
|
|
|
event_data.msg = g_strdup_vprintf (msg, ap);
|
|
|
|
va_end (ap);
|
2011-02-16 14:26:59 +03:00
|
|
|
|
|
|
|
mc_event_raise (MCEVENT_GROUP_CORE, "vfs_print_message", (gpointer) & event_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2011-04-07 16:27:46 +04:00
|
|
|
/**
|
2011-09-27 23:13:50 +04:00
|
|
|
* If it's local, reread the current directory
|
|
|
|
* from the OS.
|
2011-04-07 16:27:46 +04:00
|
|
|
*/
|
|
|
|
|
2011-09-27 23:13:50 +04:00
|
|
|
void
|
|
|
|
vfs_setup_cwd (void)
|
2011-04-07 16:27:46 +04:00
|
|
|
{
|
2013-12-02 14:38:43 +04:00
|
|
|
char *current_dir;
|
|
|
|
vfs_path_t *tmp_vpath;
|
2023-07-16 11:18:59 +03:00
|
|
|
const struct vfs_class *me;
|
2011-04-29 15:13:29 +04:00
|
|
|
|
2011-05-30 11:49:10 +04:00
|
|
|
if (vfs_get_raw_current_dir () == NULL)
|
2011-04-29 15:13:29 +04:00
|
|
|
{
|
2013-12-02 14:38:43 +04:00
|
|
|
current_dir = g_get_current_dir ();
|
|
|
|
vfs_set_raw_current_dir (vfs_path_from_str (current_dir));
|
|
|
|
g_free (current_dir);
|
|
|
|
|
|
|
|
current_dir = getenv ("PWD");
|
|
|
|
tmp_vpath = vfs_path_from_str (current_dir);
|
|
|
|
|
|
|
|
if (tmp_vpath != NULL)
|
|
|
|
{
|
2016-06-30 11:01:47 +03:00
|
|
|
if (vfs_test_current_dir (tmp_vpath))
|
2013-12-02 14:38:43 +04:00
|
|
|
vfs_set_raw_current_dir (tmp_vpath);
|
|
|
|
else
|
2021-02-21 19:30:18 +03:00
|
|
|
vfs_path_free (tmp_vpath, TRUE);
|
2013-12-02 14:38:43 +04:00
|
|
|
}
|
2011-04-29 15:13:29 +04:00
|
|
|
}
|
2011-08-15 15:37:59 +04:00
|
|
|
|
2023-07-16 11:18:59 +03:00
|
|
|
me = vfs_path_get_last_path_vfs (vfs_get_raw_current_dir ());
|
|
|
|
if ((me->flags & VFSF_LOCAL) != 0)
|
2011-04-07 16:27:46 +04:00
|
|
|
{
|
2011-07-18 01:30:58 +04:00
|
|
|
current_dir = g_get_current_dir ();
|
|
|
|
tmp_vpath = vfs_path_from_str (current_dir);
|
|
|
|
g_free (current_dir);
|
|
|
|
|
|
|
|
if (tmp_vpath != NULL)
|
2016-06-30 11:01:47 +03:00
|
|
|
{
|
|
|
|
/* One of directories in the path is not readable */
|
2011-08-15 15:37:59 +04:00
|
|
|
|
|
|
|
/* Check if it is O.K. to use the current_dir */
|
2016-06-30 11:01:47 +03:00
|
|
|
if (!vfs_test_current_dir (tmp_vpath))
|
2011-07-18 01:30:58 +04:00
|
|
|
vfs_set_raw_current_dir (tmp_vpath);
|
|
|
|
else
|
2021-02-21 19:30:18 +03:00
|
|
|
vfs_path_free (tmp_vpath, TRUE);
|
2011-04-07 16:27:46 +04:00
|
|
|
}
|
|
|
|
}
|
2011-09-27 23:13:50 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* Return current directory. If it's local, reread the current directory
|
|
|
|
* from the OS.
|
|
|
|
*/
|
|
|
|
|
|
|
|
char *
|
2023-04-08 21:25:44 +03:00
|
|
|
vfs_get_cwd (void)
|
2011-09-27 23:13:50 +04:00
|
|
|
{
|
|
|
|
vfs_setup_cwd ();
|
2023-04-08 21:25:44 +03:00
|
|
|
return vfs_get_current_dir_n ();
|
2011-04-07 16:27:46 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2011-09-20 13:40:14 +04:00
|
|
|
/**
|
|
|
|
* Preallocate space for file in new place for ensure that file
|
|
|
|
* will be fully copied with less fragmentation.
|
|
|
|
*
|
2012-08-31 18:05:29 +04:00
|
|
|
* @param dest_vfs_fd mc VFS file handler
|
2011-09-20 13:40:14 +04:00
|
|
|
* @param src_fsize source file size
|
|
|
|
* @param dest_fsize destination file size (if destination exists, otherwise should be 0)
|
|
|
|
*
|
2012-11-05 17:57:50 +04:00
|
|
|
* @return 0 if success and non-zero otherwise.
|
2011-09-20 13:40:14 +04:00
|
|
|
* Note: function doesn't touch errno global variable.
|
|
|
|
*/
|
2012-08-31 18:05:29 +04:00
|
|
|
|
2011-09-20 13:40:14 +04:00
|
|
|
int
|
|
|
|
vfs_preallocate (int dest_vfs_fd, off_t src_fsize, off_t dest_fsize)
|
|
|
|
{
|
|
|
|
#ifndef HAVE_POSIX_FALLOCATE
|
2011-10-25 23:00:53 +04:00
|
|
|
(void) dest_vfs_fd;
|
2011-09-20 13:40:14 +04:00
|
|
|
(void) src_fsize;
|
|
|
|
(void) dest_fsize;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
#else /* HAVE_POSIX_FALLOCATE */
|
2016-03-24 11:00:56 +03:00
|
|
|
void *dest_fd = NULL;
|
2011-09-20 13:40:14 +04:00
|
|
|
struct vfs_class *dest_class;
|
|
|
|
|
2016-03-24 11:00:56 +03:00
|
|
|
if (src_fsize == 0)
|
2011-09-20 13:40:14 +04:00
|
|
|
return 0;
|
|
|
|
|
2016-03-24 11:00:56 +03:00
|
|
|
dest_class = vfs_class_find_by_handle (dest_vfs_fd, &dest_fd);
|
2019-11-18 21:24:13 +03:00
|
|
|
if ((dest_class->flags & VFSF_LOCAL) == 0 || dest_fd == NULL)
|
2012-03-21 18:02:43 +04:00
|
|
|
return 0;
|
|
|
|
|
2016-03-24 11:00:56 +03:00
|
|
|
return posix_fallocate (*(int *) dest_fd, dest_fsize, src_fsize - dest_fsize);
|
2011-09-20 13:40:14 +04:00
|
|
|
|
|
|
|
#endif /* HAVE_POSIX_FALLOCATE */
|
2018-08-11 20:48:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
int
|
|
|
|
vfs_clone_file (int dest_vfs_fd, int src_vfs_fd)
|
|
|
|
{
|
|
|
|
#ifdef FICLONE
|
|
|
|
void *dest_fd = NULL;
|
|
|
|
void *src_fd = NULL;
|
|
|
|
struct vfs_class *dest_class;
|
|
|
|
struct vfs_class *src_class;
|
|
|
|
|
|
|
|
dest_class = vfs_class_find_by_handle (dest_vfs_fd, &dest_fd);
|
2019-11-18 21:24:13 +03:00
|
|
|
if ((dest_class->flags & VFSF_LOCAL) == 0)
|
2018-08-11 20:48:51 +03:00
|
|
|
{
|
2022-05-07 10:15:14 +03:00
|
|
|
errno = ENOTSUP;
|
2018-08-11 20:48:51 +03:00
|
|
|
return (-1);
|
|
|
|
}
|
2018-08-11 20:55:10 +03:00
|
|
|
if (dest_fd == NULL)
|
|
|
|
{
|
|
|
|
errno = EBADF;
|
|
|
|
return (-1);
|
|
|
|
}
|
2018-08-11 20:48:51 +03:00
|
|
|
|
|
|
|
src_class = vfs_class_find_by_handle (src_vfs_fd, &src_fd);
|
2019-11-18 21:24:13 +03:00
|
|
|
if ((src_class->flags & VFSF_LOCAL) == 0)
|
2018-08-11 20:48:51 +03:00
|
|
|
{
|
2022-05-07 10:15:14 +03:00
|
|
|
errno = ENOTSUP;
|
2018-08-11 20:48:51 +03:00
|
|
|
return (-1);
|
|
|
|
}
|
2018-08-11 20:55:10 +03:00
|
|
|
if (src_fd == NULL)
|
|
|
|
{
|
|
|
|
errno = EBADF;
|
|
|
|
return (-1);
|
|
|
|
}
|
2018-08-11 20:48:51 +03:00
|
|
|
|
|
|
|
return ioctl (*(int *) dest_fd, FICLONE, *(int *) src_fd);
|
|
|
|
#else
|
|
|
|
(void) dest_vfs_fd;
|
|
|
|
(void) src_vfs_fd;
|
2022-05-07 10:15:14 +03:00
|
|
|
errno = ENOTSUP;
|
2018-08-11 20:48:51 +03:00
|
|
|
return (-1);
|
|
|
|
#endif
|
2011-09-20 13:40:14 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|