2011-10-15 14:56:47 +04:00
|
|
|
/*
|
|
|
|
Virtual File System: interface functions
|
|
|
|
|
2023-01-03 11:30:57 +03:00
|
|
|
Copyright (C) 2011-2023
|
2014-02-12 10:33:10 +04:00
|
|
|
Free Software Foundation, Inc.
|
2011-04-07 16:27:46 +04:00
|
|
|
|
|
|
|
Written by:
|
2013-04-14 17:38:37 +04:00
|
|
|
Slava Zanko <slavazanko@gmail.com>, 2011, 2013
|
2022-05-07 10:15:14 +03:00
|
|
|
Andrew Borodin <aborodin@vmail.ru>, 2011-2022
|
2011-04-07 16:27:46 +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-07 16:27:46 +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-07 16:27:46 +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-07 16:27:46 +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-07 16:27:46 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \file
|
|
|
|
* \brief Source: Virtual File System: path handlers
|
|
|
|
* \author Slava Zanko
|
|
|
|
* \date 2011
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h> /* For atol() */
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <ctype.h> /* is_digit() */
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <dirent.h>
|
2012-01-04 12:44:35 +04:00
|
|
|
#include <pwd.h>
|
|
|
|
#include <grp.h>
|
2011-04-07 16:27:46 +04:00
|
|
|
|
|
|
|
#include "lib/global.h"
|
|
|
|
|
|
|
|
#include "lib/widget.h" /* message() */
|
2011-04-18 16:08:13 +04:00
|
|
|
#include "lib/strutil.h" /* str_crt_conv_from() */
|
2012-01-04 12:44:35 +04:00
|
|
|
#include "lib/util.h"
|
2011-04-07 16:27:46 +04:00
|
|
|
|
|
|
|
#include "vfs.h"
|
|
|
|
#include "utilvfs.h"
|
2011-04-18 16:08:13 +04:00
|
|
|
#include "path.h"
|
2011-04-07 16:27:46 +04:00
|
|
|
#include "gc.h"
|
2012-04-20 15:03:53 +04:00
|
|
|
#include "xdirentry.h"
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2015-05-10 17:55:54 +03:00
|
|
|
/* TODO: move it to separate private .h */
|
2011-04-07 16:27:46 +04:00
|
|
|
extern GString *vfs_str_buffer;
|
2016-03-03 22:51:40 +03:00
|
|
|
extern vfs_class *current_vfs;
|
2020-11-16 10:09:09 +03:00
|
|
|
extern struct vfs_dirent *mc_readdir_result;
|
2011-04-07 16:27:46 +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-07 16:27:46 +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-07 16:27:46 +04:00
|
|
|
/*** file scope functions ************************************************************************/
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2011-07-24 16:27:48 +04:00
|
|
|
static vfs_path_t *
|
|
|
|
mc_def_getlocalcopy (const vfs_path_t * filename_vpath)
|
2011-04-07 16:27:46 +04:00
|
|
|
{
|
2012-01-04 16:34:05 +04:00
|
|
|
vfs_path_t *tmp_vpath = NULL;
|
2013-10-10 16:21:26 +04:00
|
|
|
int fdin, fdout = -1;
|
2011-04-07 16:27:46 +04:00
|
|
|
ssize_t i;
|
2011-07-22 00:33:45 +04:00
|
|
|
char buffer[BUF_1K * 8];
|
2011-04-07 16:27:46 +04:00
|
|
|
struct stat mystat;
|
|
|
|
|
2011-07-24 16:27:48 +04:00
|
|
|
fdin = mc_open (filename_vpath, O_RDONLY | O_LINEAR);
|
2011-04-07 16:27:46 +04:00
|
|
|
if (fdin == -1)
|
2011-07-22 00:33:45 +04:00
|
|
|
goto fail;
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2011-07-24 16:27:48 +04:00
|
|
|
fdout = vfs_mkstemps (&tmp_vpath, "vfs", vfs_path_get_last_path_str (filename_vpath));
|
2011-04-07 16:27:46 +04:00
|
|
|
if (fdout == -1)
|
|
|
|
goto fail;
|
2011-07-22 00:33:45 +04:00
|
|
|
|
2011-04-07 16:27:46 +04:00
|
|
|
while ((i = mc_read (fdin, buffer, sizeof (buffer))) > 0)
|
|
|
|
{
|
|
|
|
if (write (fdout, buffer, i) != i)
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
if (i == -1)
|
|
|
|
goto fail;
|
|
|
|
i = mc_close (fdin);
|
|
|
|
fdin = -1;
|
|
|
|
if (i == -1)
|
|
|
|
goto fail;
|
2012-07-16 16:14:33 +04:00
|
|
|
|
2012-01-04 16:34:05 +04:00
|
|
|
i = close (fdout);
|
|
|
|
fdout = -1;
|
|
|
|
if (i == -1)
|
2011-04-07 16:27:46 +04:00
|
|
|
goto fail;
|
|
|
|
|
2011-07-24 16:27:48 +04:00
|
|
|
if (mc_stat (filename_vpath, &mystat) != -1)
|
2012-01-04 16:34:05 +04:00
|
|
|
mc_chmod (tmp_vpath, mystat.st_mode);
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2011-07-24 16:27:48 +04:00
|
|
|
return tmp_vpath;
|
2011-04-07 16:27:46 +04:00
|
|
|
|
|
|
|
fail:
|
2021-02-21 19:30:18 +03:00
|
|
|
vfs_path_free (tmp_vpath, TRUE);
|
2011-04-07 16:27:46 +04:00
|
|
|
if (fdout != -1)
|
|
|
|
close (fdout);
|
|
|
|
if (fdin != -1)
|
|
|
|
mc_close (fdin);
|
2011-07-24 16:27:48 +04:00
|
|
|
return NULL;
|
2011-04-07 16:27:46 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
static int
|
2011-07-24 16:27:48 +04:00
|
|
|
mc_def_ungetlocalcopy (const vfs_path_t * filename_vpath,
|
|
|
|
const vfs_path_t * local_vpath, gboolean has_changed)
|
2011-04-07 16:27:46 +04:00
|
|
|
{
|
|
|
|
int fdin = -1, fdout = -1;
|
2012-01-03 13:35:57 +04:00
|
|
|
const char *local;
|
2011-07-22 00:33:45 +04:00
|
|
|
|
2011-07-24 16:27:48 +04:00
|
|
|
local = vfs_path_get_last_path_str (local_vpath);
|
2011-07-22 00:33:45 +04:00
|
|
|
|
2011-04-07 16:27:46 +04:00
|
|
|
if (has_changed)
|
|
|
|
{
|
2011-07-22 00:33:45 +04:00
|
|
|
char buffer[BUF_1K * 8];
|
2011-04-07 16:27:46 +04:00
|
|
|
ssize_t i;
|
|
|
|
|
2011-07-24 16:27:48 +04:00
|
|
|
if (vfs_path_get_last_path_vfs (filename_vpath)->write == NULL)
|
2011-04-07 16:27:46 +04:00
|
|
|
goto failed;
|
|
|
|
|
|
|
|
fdin = open (local, O_RDONLY);
|
|
|
|
if (fdin == -1)
|
|
|
|
goto failed;
|
2011-07-24 16:27:48 +04:00
|
|
|
fdout = mc_open (filename_vpath, O_WRONLY | O_TRUNC);
|
2011-04-07 16:27:46 +04:00
|
|
|
if (fdout == -1)
|
|
|
|
goto failed;
|
|
|
|
while ((i = read (fdin, buffer, sizeof (buffer))) > 0)
|
|
|
|
if (mc_write (fdout, buffer, (size_t) i) != i)
|
|
|
|
goto failed;
|
|
|
|
if (i == -1)
|
|
|
|
goto failed;
|
|
|
|
|
|
|
|
if (close (fdin) == -1)
|
|
|
|
{
|
|
|
|
fdin = -1;
|
|
|
|
goto failed;
|
|
|
|
}
|
|
|
|
fdin = -1;
|
|
|
|
if (mc_close (fdout) == -1)
|
|
|
|
{
|
|
|
|
fdout = -1;
|
|
|
|
goto failed;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
unlink (local);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
failed:
|
2011-07-24 16:27:48 +04:00
|
|
|
message (D_ERROR, _("Changes to file lost"), "%s", vfs_path_get_last_path_str (filename_vpath));
|
2011-04-07 16:27:46 +04:00
|
|
|
if (fdout != -1)
|
|
|
|
mc_close (fdout);
|
|
|
|
if (fdin != -1)
|
|
|
|
close (fdin);
|
|
|
|
unlink (local);
|
2019-09-21 14:01:15 +03:00
|
|
|
return (-1);
|
2011-04-07 16:27:46 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/*** public functions ****************************************************************************/
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
int
|
2011-07-22 00:33:45 +04:00
|
|
|
mc_open (const vfs_path_t * vpath, int flags, ...)
|
2011-04-07 16:27:46 +04:00
|
|
|
{
|
2015-11-21 17:21:23 +03:00
|
|
|
int result = -1;
|
|
|
|
mode_t mode = 0;
|
2023-07-16 11:18:59 +03:00
|
|
|
struct vfs_class *me;
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2011-04-18 16:08:13 +04:00
|
|
|
if (vpath == NULL)
|
2019-09-21 14:01:15 +03:00
|
|
|
return (-1);
|
2011-04-07 16:27:46 +04:00
|
|
|
|
|
|
|
/* Get the mode flag */
|
2019-09-21 14:01:15 +03:00
|
|
|
if ((flags & O_CREAT) != 0)
|
2011-04-07 16:27:46 +04:00
|
|
|
{
|
2011-04-18 16:08:13 +04:00
|
|
|
va_list ap;
|
2019-09-21 14:01:15 +03:00
|
|
|
|
2011-04-07 16:27:46 +04:00
|
|
|
va_start (ap, flags);
|
2016-03-16 18:10:48 +03:00
|
|
|
/* We have to use PROMOTED_MODE_T instead of mode_t. Doing 'va_arg (ap, mode_t)'
|
|
|
|
* fails on systems where 'mode_t' is smaller than 'int' because of C's "default
|
|
|
|
* argument promotions". */
|
|
|
|
mode = va_arg (ap, PROMOTED_MODE_T);
|
2011-04-07 16:27:46 +04:00
|
|
|
va_end (ap);
|
|
|
|
}
|
|
|
|
|
2023-07-16 11:18:59 +03:00
|
|
|
me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath));
|
|
|
|
if (me != NULL && me->open != NULL)
|
2011-04-07 16:27:46 +04:00
|
|
|
{
|
2011-04-18 16:08:13 +04:00
|
|
|
void *info;
|
2019-09-21 14:01:15 +03:00
|
|
|
|
2011-04-18 16:08:13 +04:00
|
|
|
/* open must be supported */
|
2023-07-16 11:18:59 +03:00
|
|
|
info = me->open (vpath, flags, mode);
|
2011-04-18 16:08:13 +04:00
|
|
|
if (info == NULL)
|
2023-07-16 11:18:59 +03:00
|
|
|
errno = vfs_ferrno (me);
|
2011-04-18 16:08:13 +04:00
|
|
|
else
|
2023-07-16 11:18:59 +03:00
|
|
|
result = vfs_new_handle (me, info);
|
2011-04-07 16:27:46 +04:00
|
|
|
}
|
2011-04-18 16:08:13 +04:00
|
|
|
else
|
2022-05-07 10:15:14 +03:00
|
|
|
errno = ENOTSUP;
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2011-04-18 16:08:13 +04:00
|
|
|
return result;
|
2011-04-07 16:27:46 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/* *INDENT-OFF* */
|
|
|
|
|
|
|
|
#define MC_NAMEOP(name, inarg, callarg) \
|
|
|
|
int mc_##name inarg \
|
|
|
|
{ \
|
|
|
|
int result; \
|
2023-07-16 11:18:59 +03:00
|
|
|
struct vfs_class *me; \
|
2011-04-18 16:08:13 +04:00
|
|
|
\
|
|
|
|
if (vpath == NULL) \
|
2019-09-21 14:01:15 +03:00
|
|
|
return (-1); \
|
2011-04-18 16:08:13 +04:00
|
|
|
\
|
2023-07-16 11:18:59 +03:00
|
|
|
me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath)); \
|
|
|
|
if (me == NULL) \
|
2019-09-21 14:01:15 +03:00
|
|
|
return (-1); \
|
2011-04-18 16:08:13 +04:00
|
|
|
\
|
2023-07-16 11:18:59 +03:00
|
|
|
result = me->name != NULL ? me->name callarg : -1; \
|
2011-04-07 16:27:46 +04:00
|
|
|
if (result == -1) \
|
2023-07-16 11:18:59 +03:00
|
|
|
errno = me->name != NULL ? vfs_ferrno (me) : ENOTSUP; \
|
2011-04-07 16:27:46 +04:00
|
|
|
return result; \
|
|
|
|
}
|
|
|
|
|
2011-07-21 01:22:50 +04:00
|
|
|
MC_NAMEOP (chmod, (const vfs_path_t *vpath, mode_t mode), (vpath, mode))
|
|
|
|
MC_NAMEOP (chown, (const vfs_path_t *vpath, uid_t owner, gid_t group), (vpath, owner, group))
|
2023-03-17 19:53:37 +03:00
|
|
|
MC_NAMEOP (fgetflags, (const vfs_path_t *vpath, unsigned long *flags), (vpath, flags))
|
|
|
|
MC_NAMEOP (fsetflags, (const vfs_path_t *vpath, unsigned long flags), (vpath, flags))
|
2015-12-07 02:39:05 +03:00
|
|
|
MC_NAMEOP (utime, (const vfs_path_t *vpath, mc_timesbuf_t * times), (vpath, times))
|
2011-07-21 01:22:50 +04:00
|
|
|
MC_NAMEOP (readlink, (const vfs_path_t *vpath, char *buf, size_t bufsiz), (vpath, buf, bufsiz))
|
|
|
|
MC_NAMEOP (unlink, (const vfs_path_t *vpath), (vpath))
|
|
|
|
MC_NAMEOP (mkdir, (const vfs_path_t *vpath, mode_t mode), (vpath, mode))
|
|
|
|
MC_NAMEOP (rmdir, (const vfs_path_t *vpath), (vpath))
|
|
|
|
MC_NAMEOP (mknod, (const vfs_path_t *vpath, mode_t mode, dev_t dev), (vpath, mode, dev))
|
2011-04-07 16:27:46 +04:00
|
|
|
|
|
|
|
/* *INDENT-ON* */
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
int
|
2011-07-22 00:33:45 +04:00
|
|
|
mc_symlink (const vfs_path_t * vpath1, const vfs_path_t * vpath2)
|
2011-04-07 16:27:46 +04:00
|
|
|
{
|
2011-04-18 16:08:13 +04:00
|
|
|
int result = -1;
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2019-09-21 14:03:02 +03:00
|
|
|
if (vpath1 != NULL && vpath2 != NULL)
|
2011-04-07 16:27:46 +04:00
|
|
|
{
|
2023-07-16 11:18:59 +03:00
|
|
|
struct vfs_class *me;
|
2011-07-21 19:24:20 +04:00
|
|
|
|
2023-07-16 11:18:59 +03:00
|
|
|
me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath2));
|
|
|
|
if (me != NULL)
|
2011-04-21 11:46:20 +04:00
|
|
|
{
|
2023-07-16 11:18:59 +03:00
|
|
|
result = me->symlink != NULL ? me->symlink (vpath1, vpath2) : -1;
|
2011-04-21 11:46:20 +04:00
|
|
|
if (result == -1)
|
2023-07-16 11:18:59 +03:00
|
|
|
errno = me->symlink != NULL ? vfs_ferrno (me) : ENOTSUP;
|
2011-04-21 11:46:20 +04:00
|
|
|
}
|
2011-04-07 16:27:46 +04:00
|
|
|
}
|
2011-04-18 16:08:13 +04:00
|
|
|
return result;
|
2011-04-07 16:27:46 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/* *INDENT-OFF* */
|
|
|
|
|
2023-07-16 14:55:48 +03:00
|
|
|
#define MC_HANDLEOP(rettype, name, inarg, callarg) \
|
|
|
|
rettype mc_##name inarg \
|
2011-04-07 16:27:46 +04:00
|
|
|
{ \
|
|
|
|
struct vfs_class *vfs; \
|
2016-03-24 11:00:56 +03:00
|
|
|
void *fsinfo = NULL; \
|
2023-07-16 14:55:48 +03:00
|
|
|
rettype result; \
|
2019-09-21 14:01:15 +03:00
|
|
|
\
|
2011-04-07 16:27:46 +04:00
|
|
|
if (handle == -1) \
|
2019-09-21 14:01:15 +03:00
|
|
|
return (-1); \
|
|
|
|
\
|
2016-03-24 11:00:56 +03:00
|
|
|
vfs = vfs_class_find_by_handle (handle, &fsinfo); \
|
2011-04-07 16:27:46 +04:00
|
|
|
if (vfs == NULL) \
|
2019-09-21 14:01:15 +03:00
|
|
|
return (-1); \
|
|
|
|
\
|
2023-07-16 14:55:48 +03:00
|
|
|
result = vfs->name != NULL ? vfs->name callarg : -1; \
|
2011-04-07 16:27:46 +04:00
|
|
|
if (result == -1) \
|
2022-05-07 10:15:14 +03:00
|
|
|
errno = vfs->name != NULL ? vfs_ferrno (vfs) : ENOTSUP; \
|
2011-04-07 16:27:46 +04:00
|
|
|
return result; \
|
|
|
|
}
|
|
|
|
|
2023-07-16 14:55:48 +03:00
|
|
|
MC_HANDLEOP (ssize_t, read, (int handle, void *buf, size_t count), (fsinfo, buf, count))
|
|
|
|
MC_HANDLEOP (ssize_t, write, (int handle, const void *buf, size_t count), (fsinfo, buf, count))
|
|
|
|
MC_HANDLEOP (int, fstat, (int handle, struct stat *buf), (fsinfo, buf))
|
2011-04-07 16:27:46 +04:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
#define MC_RENAMEOP(name) \
|
2011-07-21 01:51:42 +04:00
|
|
|
int mc_##name (const vfs_path_t *vpath1, const vfs_path_t *vpath2) \
|
2011-04-07 16:27:46 +04:00
|
|
|
{ \
|
|
|
|
int result; \
|
2023-07-16 11:18:59 +03:00
|
|
|
struct vfs_class *me1, *me2; \
|
2011-04-18 16:08:13 +04:00
|
|
|
\
|
2011-07-21 01:51:42 +04:00
|
|
|
if (vpath1 == NULL || vpath2 == NULL) \
|
2019-09-21 14:01:15 +03:00
|
|
|
return (-1); \
|
2011-04-18 16:08:13 +04:00
|
|
|
\
|
2023-07-16 11:18:59 +03:00
|
|
|
me1 = VFS_CLASS (vfs_path_get_last_path_vfs (vpath1)); \
|
|
|
|
me2 = VFS_CLASS (vfs_path_get_last_path_vfs (vpath2)); \
|
2011-04-18 16:08:13 +04:00
|
|
|
\
|
2023-07-16 11:18:59 +03:00
|
|
|
if (me1 == NULL || me2 == NULL || me1 != me2) \
|
2011-04-07 16:27:46 +04:00
|
|
|
{ \
|
|
|
|
errno = EXDEV; \
|
2019-09-21 14:01:15 +03:00
|
|
|
return (-1); \
|
|
|
|
} \
|
2011-04-18 16:08:13 +04:00
|
|
|
\
|
2023-07-16 11:18:59 +03:00
|
|
|
result = me1->name != NULL ? me1->name (vpath1, vpath2) : -1; \
|
2011-04-07 16:27:46 +04:00
|
|
|
if (result == -1) \
|
2023-07-16 11:18:59 +03:00
|
|
|
errno = me1->name != NULL ? vfs_ferrno (me1) : ENOTSUP; \
|
2011-04-07 16:27:46 +04:00
|
|
|
return result; \
|
|
|
|
}
|
|
|
|
|
|
|
|
MC_RENAMEOP (link)
|
|
|
|
MC_RENAMEOP (rename)
|
|
|
|
|
|
|
|
/* *INDENT-ON* */
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
int
|
|
|
|
mc_ctl (int handle, int ctlop, void *arg)
|
|
|
|
{
|
2016-03-24 11:00:56 +03:00
|
|
|
struct vfs_class *vfs;
|
|
|
|
void *fsinfo = NULL;
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2016-03-24 11:00:56 +03:00
|
|
|
vfs = vfs_class_find_by_handle (handle, &fsinfo);
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2016-07-07 15:42:03 +03:00
|
|
|
return (vfs == NULL || vfs->ctl == NULL) ? 0 : vfs->ctl (fsinfo, ctlop, arg);
|
2011-04-07 16:27:46 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
int
|
2011-07-21 00:12:02 +04:00
|
|
|
mc_setctl (const vfs_path_t * vpath, int ctlop, void *arg)
|
2011-04-07 16:27:46 +04:00
|
|
|
{
|
|
|
|
int result = -1;
|
2023-07-16 11:18:59 +03:00
|
|
|
struct vfs_class *me;
|
2011-04-18 16:08:13 +04:00
|
|
|
|
|
|
|
if (vpath == NULL)
|
2011-04-07 16:27:46 +04:00
|
|
|
vfs_die ("You don't want to pass NULL to mc_setctl.");
|
|
|
|
|
2023-07-16 11:18:59 +03:00
|
|
|
me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath));
|
|
|
|
if (me != NULL)
|
|
|
|
result = me->setctl != NULL ? me->setctl (vpath, ctlop, arg) : 0;
|
2011-04-07 16:27:46 +04:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
int
|
|
|
|
mc_close (int handle)
|
|
|
|
{
|
|
|
|
struct vfs_class *vfs;
|
2016-03-24 11:00:56 +03:00
|
|
|
void *fsinfo = NULL;
|
2011-04-07 16:27:46 +04:00
|
|
|
int result;
|
|
|
|
|
2016-03-24 11:00:56 +03:00
|
|
|
if (handle == -1)
|
2019-09-21 14:01:15 +03:00
|
|
|
return (-1);
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2016-03-24 11:00:56 +03:00
|
|
|
vfs = vfs_class_find_by_handle (handle, &fsinfo);
|
|
|
|
if (vfs == NULL || fsinfo == NULL)
|
2019-09-21 14:01:15 +03:00
|
|
|
return (-1);
|
2011-04-07 16:27:46 +04:00
|
|
|
|
|
|
|
if (handle < 3)
|
|
|
|
return close (handle);
|
|
|
|
|
2019-09-21 14:01:15 +03:00
|
|
|
if (vfs->close == NULL)
|
2011-04-07 16:27:46 +04:00
|
|
|
vfs_die ("VFS must support close.\n");
|
2019-09-21 14:01:15 +03:00
|
|
|
result = vfs->close (fsinfo);
|
2011-04-07 16:27:46 +04:00
|
|
|
vfs_free_handle (handle);
|
|
|
|
if (result == -1)
|
|
|
|
errno = vfs_ferrno (vfs);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
DIR *
|
2011-07-18 22:07:39 +04:00
|
|
|
mc_opendir (const vfs_path_t * vpath)
|
2011-04-07 16:27:46 +04:00
|
|
|
{
|
|
|
|
int handle, *handlep;
|
|
|
|
void *info;
|
2011-04-20 16:59:06 +04:00
|
|
|
vfs_path_element_t *path_element;
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2011-04-20 16:59:06 +04:00
|
|
|
if (vpath == NULL)
|
|
|
|
return NULL;
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2012-01-03 13:35:57 +04:00
|
|
|
path_element = (vfs_path_element_t *) vfs_path_get_by_index (vpath, -1);
|
2011-06-17 14:28:37 +04:00
|
|
|
if (!vfs_path_element_valid (path_element))
|
|
|
|
{
|
2022-05-07 10:15:14 +03:00
|
|
|
errno = ENOTSUP;
|
2011-06-17 14:28:37 +04:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-09-21 14:01:15 +03:00
|
|
|
info = path_element->class->opendir ? path_element->class->opendir (vpath) : NULL;
|
2011-04-20 16:59:06 +04:00
|
|
|
if (info == NULL)
|
2011-04-07 16:27:46 +04:00
|
|
|
{
|
2022-05-07 10:15:14 +03:00
|
|
|
errno = path_element->class->opendir ? vfs_ferrno (path_element->class) : ENOTSUP;
|
2011-04-07 16:27:46 +04:00
|
|
|
return NULL;
|
|
|
|
}
|
2011-04-20 16:59:06 +04:00
|
|
|
|
2011-05-27 19:28:46 +04:00
|
|
|
path_element->dir.info = info;
|
2011-04-20 16:59:06 +04:00
|
|
|
|
2012-04-30 14:58:25 +04:00
|
|
|
#ifdef HAVE_CHARSET
|
2012-01-03 13:35:57 +04:00
|
|
|
path_element->dir.converter = (path_element->encoding != NULL) ?
|
2012-02-07 15:54:58 +04:00
|
|
|
str_crt_conv_from (path_element->encoding) : str_cnv_from_term;
|
2011-05-27 19:28:46 +04:00
|
|
|
if (path_element->dir.converter == INVALID_CONV)
|
|
|
|
path_element->dir.converter = str_cnv_from_term;
|
2012-04-30 14:58:25 +04:00
|
|
|
#endif
|
2011-04-20 16:59:06 +04:00
|
|
|
|
2011-06-19 15:33:04 +04:00
|
|
|
handle = vfs_new_handle (path_element->class, vfs_path_element_clone (path_element));
|
2011-04-20 16:59:06 +04:00
|
|
|
|
|
|
|
handlep = g_new (int, 1);
|
|
|
|
*handlep = handle;
|
|
|
|
return (DIR *) handlep;
|
2011-04-07 16:27:46 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2020-11-16 10:09:09 +03:00
|
|
|
struct vfs_dirent *
|
2011-04-07 16:27:46 +04:00
|
|
|
mc_readdir (DIR * dirp)
|
|
|
|
{
|
|
|
|
int handle;
|
|
|
|
struct vfs_class *vfs;
|
2016-03-24 11:00:56 +03:00
|
|
|
void *fsinfo = NULL;
|
2020-11-16 10:09:09 +03:00
|
|
|
struct vfs_dirent *entry = NULL;
|
2011-05-27 19:28:46 +04:00
|
|
|
vfs_path_element_t *vfs_path_element;
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2019-09-21 14:01:15 +03:00
|
|
|
if (dirp == NULL)
|
2011-04-07 16:27:46 +04:00
|
|
|
{
|
|
|
|
errno = EFAULT;
|
|
|
|
return NULL;
|
|
|
|
}
|
2019-09-21 14:01:15 +03:00
|
|
|
|
2011-04-07 16:27:46 +04:00
|
|
|
handle = *(int *) dirp;
|
|
|
|
|
2016-03-24 11:00:56 +03:00
|
|
|
vfs = vfs_class_find_by_handle (handle, &fsinfo);
|
|
|
|
if (vfs == NULL || fsinfo == NULL)
|
2011-04-07 16:27:46 +04:00
|
|
|
return NULL;
|
|
|
|
|
2016-03-24 11:00:56 +03:00
|
|
|
vfs_path_element = (vfs_path_element_t *) fsinfo;
|
2019-09-21 14:01:15 +03:00
|
|
|
if (vfs->readdir != NULL)
|
2011-04-07 16:27:46 +04:00
|
|
|
{
|
2019-09-21 14:01:15 +03:00
|
|
|
entry = vfs->readdir (vfs_path_element->dir.info);
|
2011-04-07 16:27:46 +04:00
|
|
|
if (entry == NULL)
|
|
|
|
return NULL;
|
2012-04-30 14:58:25 +04:00
|
|
|
|
2011-04-07 16:27:46 +04:00
|
|
|
g_string_set_size (vfs_str_buffer, 0);
|
2012-04-30 14:58:25 +04:00
|
|
|
#ifdef HAVE_CHARSET
|
2013-01-17 16:21:35 +04:00
|
|
|
str_vfs_convert_from (vfs_path_element->dir.converter, entry->d_name, vfs_str_buffer);
|
2012-04-30 14:58:25 +04:00
|
|
|
#else
|
|
|
|
g_string_assign (vfs_str_buffer, entry->d_name);
|
|
|
|
#endif
|
2020-11-16 10:09:09 +03:00
|
|
|
vfs_dirent_assign (mc_readdir_result, vfs_str_buffer->str, entry->d_ino);
|
|
|
|
vfs_dirent_free (entry);
|
2011-04-07 16:27:46 +04:00
|
|
|
}
|
|
|
|
if (entry == NULL)
|
2022-05-07 10:15:14 +03:00
|
|
|
errno = vfs->readdir ? vfs_ferrno (vfs) : ENOTSUP;
|
2011-04-07 16:27:46 +04:00
|
|
|
return (entry != NULL) ? mc_readdir_result : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
int
|
|
|
|
mc_closedir (DIR * dirp)
|
|
|
|
{
|
2016-03-24 11:07:09 +03:00
|
|
|
int handle;
|
2011-04-07 16:27:46 +04:00
|
|
|
struct vfs_class *vfs;
|
2016-03-24 11:00:56 +03:00
|
|
|
void *fsinfo = NULL;
|
2011-04-07 16:27:46 +04:00
|
|
|
int result = -1;
|
|
|
|
|
2016-03-24 11:07:09 +03:00
|
|
|
if (dirp == NULL)
|
|
|
|
return result;
|
|
|
|
|
|
|
|
handle = *(int *) dirp;
|
|
|
|
|
2016-03-24 11:00:56 +03:00
|
|
|
vfs = vfs_class_find_by_handle (handle, &fsinfo);
|
|
|
|
if (vfs != NULL && fsinfo != NULL)
|
2011-04-07 16:27:46 +04:00
|
|
|
{
|
2016-03-24 11:00:56 +03:00
|
|
|
vfs_path_element_t *vfs_path_element = (vfs_path_element_t *) fsinfo;
|
2012-04-30 14:58:25 +04:00
|
|
|
|
|
|
|
#ifdef HAVE_CHARSET
|
2011-05-27 19:28:46 +04:00
|
|
|
if (vfs_path_element->dir.converter != str_cnv_from_term)
|
2011-06-01 14:56:52 +04:00
|
|
|
{
|
2011-05-27 19:28:46 +04:00
|
|
|
str_close_conv (vfs_path_element->dir.converter);
|
2011-06-01 14:56:52 +04:00
|
|
|
vfs_path_element->dir.converter = INVALID_CONV;
|
|
|
|
}
|
2012-04-30 14:58:25 +04:00
|
|
|
#endif
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2011-05-27 19:28:46 +04:00
|
|
|
result = vfs->closedir ? (*vfs->closedir) (vfs_path_element->dir.info) : -1;
|
2011-04-07 16:27:46 +04:00
|
|
|
vfs_free_handle (handle);
|
2011-05-27 19:28:46 +04:00
|
|
|
vfs_path_element_free (vfs_path_element);
|
2011-04-07 16:27:46 +04:00
|
|
|
}
|
|
|
|
g_free (dirp);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2023-07-16 14:07:33 +03:00
|
|
|
/* *INDENT-OFF* */
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2023-07-16 14:07:33 +03:00
|
|
|
#define MC_STATOP(name) \
|
|
|
|
int mc_##name (const vfs_path_t *vpath, struct stat *buf) \
|
|
|
|
{ \
|
|
|
|
int result = -1; \
|
2023-07-16 11:18:59 +03:00
|
|
|
struct vfs_class *me; \
|
2023-07-16 14:07:33 +03:00
|
|
|
\
|
|
|
|
if (vpath == NULL) \
|
|
|
|
return (-1); \
|
|
|
|
\
|
2023-07-16 11:18:59 +03:00
|
|
|
me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath)); \
|
|
|
|
if (me != NULL) \
|
2023-07-16 14:07:33 +03:00
|
|
|
{ \
|
2023-07-16 11:18:59 +03:00
|
|
|
result = me->name ? me->name (vpath, buf) : -1; \
|
2023-07-16 14:07:33 +03:00
|
|
|
if (result == -1) \
|
2023-07-16 11:18:59 +03:00
|
|
|
errno = me->name ? vfs_ferrno (me) : ENOTSUP; \
|
2023-07-16 14:07:33 +03:00
|
|
|
} \
|
|
|
|
\
|
|
|
|
return result; \
|
2011-04-07 16:27:46 +04:00
|
|
|
}
|
|
|
|
|
2023-07-16 14:07:33 +03:00
|
|
|
MC_STATOP (stat)
|
|
|
|
MC_STATOP (lstat)
|
2011-04-07 16:27:46 +04:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2011-07-24 16:27:48 +04:00
|
|
|
vfs_path_t *
|
|
|
|
mc_getlocalcopy (const vfs_path_t * pathname_vpath)
|
2011-04-07 16:27:46 +04:00
|
|
|
{
|
2011-07-24 16:27:48 +04:00
|
|
|
vfs_path_t *result = NULL;
|
2023-07-16 11:18:59 +03:00
|
|
|
struct vfs_class *me;
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2011-07-24 16:27:48 +04:00
|
|
|
if (pathname_vpath == NULL)
|
2011-04-18 16:08:13 +04:00
|
|
|
return NULL;
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2023-07-16 11:18:59 +03:00
|
|
|
me = VFS_CLASS (vfs_path_get_last_path_vfs (pathname_vpath));
|
|
|
|
if (me != NULL)
|
2011-04-18 16:08:13 +04:00
|
|
|
{
|
2023-07-16 11:18:59 +03:00
|
|
|
result = me->getlocalcopy != NULL ?
|
|
|
|
me->getlocalcopy (pathname_vpath) : mc_def_getlocalcopy (pathname_vpath);
|
2011-04-07 16:27:46 +04:00
|
|
|
if (result == NULL)
|
2023-07-16 11:18:59 +03:00
|
|
|
errno = vfs_ferrno (me);
|
2011-04-07 16:27:46 +04:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
int
|
2011-07-24 16:27:48 +04:00
|
|
|
mc_ungetlocalcopy (const vfs_path_t * pathname_vpath, const vfs_path_t * local_vpath,
|
|
|
|
gboolean has_changed)
|
2011-04-07 16:27:46 +04:00
|
|
|
{
|
2019-09-21 14:01:15 +03:00
|
|
|
int result = -1;
|
2023-07-16 11:18:59 +03:00
|
|
|
const struct vfs_class *me;
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2011-07-24 16:27:48 +04:00
|
|
|
if (pathname_vpath == NULL)
|
2019-09-21 14:01:15 +03:00
|
|
|
return (-1);
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2023-07-16 11:18:59 +03:00
|
|
|
me = vfs_path_get_last_path_vfs (pathname_vpath);
|
|
|
|
if (me != NULL)
|
|
|
|
result = me->ungetlocalcopy != NULL ?
|
|
|
|
me->ungetlocalcopy (pathname_vpath, local_vpath, has_changed) :
|
2011-07-24 16:27:48 +04:00
|
|
|
mc_def_ungetlocalcopy (pathname_vpath, local_vpath, has_changed);
|
|
|
|
|
2019-09-21 14:01:15 +03:00
|
|
|
return result;
|
2011-04-07 16:27:46 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* VFS chdir.
|
2011-07-17 20:20:35 +04:00
|
|
|
*
|
2022-05-07 11:16:12 +03:00
|
|
|
* @param vpath VFS path.
|
|
|
|
* May be NULL. In this case NULL is returned and errno set to 0.
|
2011-07-17 20:20:35 +04:00
|
|
|
*
|
|
|
|
* @return 0 on success, -1 on failure.
|
2011-04-07 16:27:46 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
2011-07-17 20:20:35 +04:00
|
|
|
mc_chdir (const vfs_path_t * vpath)
|
2011-04-07 16:27:46 +04:00
|
|
|
{
|
2011-04-20 16:59:06 +04:00
|
|
|
struct vfs_class *old_vfs;
|
2011-04-07 16:27:46 +04:00
|
|
|
vfsid old_vfsid;
|
|
|
|
int result;
|
2023-07-16 11:18:59 +03:00
|
|
|
struct vfs_class *me;
|
2012-01-03 13:35:57 +04:00
|
|
|
const vfs_path_element_t *path_element;
|
2012-03-22 15:11:31 +04:00
|
|
|
vfs_path_t *cd_vpath;
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2011-04-20 16:59:06 +04:00
|
|
|
if (vpath == NULL)
|
2022-05-07 11:16:12 +03:00
|
|
|
{
|
|
|
|
errno = 0;
|
2019-09-21 14:01:15 +03:00
|
|
|
return (-1);
|
2022-05-07 11:16:12 +03:00
|
|
|
}
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2012-03-22 15:11:31 +04:00
|
|
|
if (vpath->relative)
|
|
|
|
cd_vpath = vfs_path_to_absolute (vpath);
|
|
|
|
else
|
|
|
|
cd_vpath = vfs_path_clone (vpath);
|
|
|
|
|
2023-07-16 11:18:59 +03:00
|
|
|
me = VFS_CLASS (vfs_path_get_last_path_vfs (cd_vpath));
|
|
|
|
if (me == NULL)
|
2022-05-07 11:16:12 +03:00
|
|
|
{
|
|
|
|
errno = EINVAL;
|
2012-03-22 15:11:31 +04:00
|
|
|
goto error_end;
|
2022-05-07 11:16:12 +03:00
|
|
|
}
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2023-07-16 11:18:59 +03:00
|
|
|
if (me->chdir == NULL)
|
2022-05-07 11:16:12 +03:00
|
|
|
{
|
|
|
|
errno = ENOTSUP;
|
|
|
|
goto error_end;
|
|
|
|
}
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2023-07-16 11:18:59 +03:00
|
|
|
result = me->chdir (cd_vpath);
|
2011-04-20 16:59:06 +04:00
|
|
|
if (result == -1)
|
|
|
|
{
|
2023-07-16 11:18:59 +03:00
|
|
|
errno = vfs_ferrno (me);
|
2012-03-22 15:11:31 +04:00
|
|
|
goto error_end;
|
2011-04-20 16:59:06 +04:00
|
|
|
}
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2011-04-29 15:13:29 +04:00
|
|
|
old_vfsid = vfs_getid (vfs_get_raw_current_dir ());
|
|
|
|
old_vfs = current_vfs;
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2011-04-20 16:59:06 +04:00
|
|
|
/* Actually change directory */
|
2012-03-22 15:11:31 +04:00
|
|
|
vfs_set_raw_current_dir (cd_vpath);
|
2023-07-16 11:18:59 +03:00
|
|
|
current_vfs = me;
|
2011-04-20 16:59:06 +04:00
|
|
|
|
|
|
|
/* This function uses the new current_dir implicitly */
|
|
|
|
vfs_stamp_create (old_vfs, old_vfsid);
|
|
|
|
|
|
|
|
/* Sometimes we assume no trailing slash on cwd */
|
2011-04-29 15:13:29 +04:00
|
|
|
path_element = vfs_path_get_by_index (vfs_get_raw_current_dir (), -1);
|
2012-04-20 15:03:53 +04:00
|
|
|
if (vfs_path_element_valid (path_element))
|
2011-04-07 16:27:46 +04:00
|
|
|
{
|
2012-04-20 15:03:53 +04:00
|
|
|
if (*path_element->path != '\0')
|
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
p = strchr (path_element->path, 0) - 1;
|
2015-01-07 11:34:53 +03:00
|
|
|
if (IS_PATH_SEP (*p) && p > path_element->path)
|
2012-04-20 15:03:53 +04:00
|
|
|
*p = '\0';
|
|
|
|
}
|
2012-05-02 16:37:06 +04:00
|
|
|
|
2012-06-25 12:18:00 +04:00
|
|
|
#ifdef ENABLE_VFS_NET
|
2012-04-20 15:03:53 +04:00
|
|
|
{
|
2012-06-25 12:18:00 +04:00
|
|
|
struct vfs_s_super *super;
|
|
|
|
|
|
|
|
super = vfs_get_super_by_vpath (vpath);
|
|
|
|
if (super != NULL && super->path_element != NULL)
|
|
|
|
{
|
|
|
|
g_free (super->path_element->path);
|
|
|
|
super->path_element->path = g_strdup (path_element->path);
|
|
|
|
}
|
2012-04-20 15:03:53 +04:00
|
|
|
}
|
2012-06-25 12:18:00 +04:00
|
|
|
#endif /* ENABLE_VFS_NET */
|
2011-04-07 16:27:46 +04:00
|
|
|
}
|
2012-05-02 16:37:06 +04:00
|
|
|
|
2011-04-20 16:59:06 +04:00
|
|
|
return 0;
|
2012-03-22 15:11:31 +04:00
|
|
|
|
|
|
|
error_end:
|
2021-02-21 19:30:18 +03:00
|
|
|
vfs_path_free (cd_vpath, TRUE);
|
2019-09-21 14:01:15 +03:00
|
|
|
return (-1);
|
2011-04-07 16:27:46 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
off_t
|
|
|
|
mc_lseek (int fd, off_t offset, int whence)
|
|
|
|
{
|
|
|
|
struct vfs_class *vfs;
|
2016-03-24 11:00:56 +03:00
|
|
|
void *fsinfo = NULL;
|
2011-04-07 16:27:46 +04:00
|
|
|
off_t result;
|
|
|
|
|
|
|
|
if (fd == -1)
|
2019-09-21 14:01:15 +03:00
|
|
|
return (-1);
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2016-03-24 11:00:56 +03:00
|
|
|
vfs = vfs_class_find_by_handle (fd, &fsinfo);
|
2011-04-07 16:27:46 +04:00
|
|
|
if (vfs == NULL)
|
2019-09-21 14:01:15 +03:00
|
|
|
return (-1);
|
2011-04-07 16:27:46 +04:00
|
|
|
|
2019-09-21 14:01:15 +03:00
|
|
|
result = vfs->lseek ? vfs->lseek (fsinfo, offset, whence) : -1;
|
2011-04-07 16:27:46 +04:00
|
|
|
if (result == -1)
|
2022-05-07 10:15:14 +03:00
|
|
|
errno = vfs->lseek ? vfs_ferrno (vfs) : ENOTSUP;
|
2011-04-07 16:27:46 +04:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2012-01-04 12:44:35 +04:00
|
|
|
/* Following code heavily borrows from libiberty, mkstemps.c */
|
|
|
|
/*
|
|
|
|
* Arguments:
|
|
|
|
* pname (output) - pointer to the name of the temp file (needs g_free).
|
|
|
|
* NULL if the function fails.
|
|
|
|
* prefix - part of the filename before the random part.
|
|
|
|
* Prepend $TMPDIR or /tmp if there are no path separators.
|
|
|
|
* suffix - if not NULL, part of the filename after the random part.
|
|
|
|
*
|
|
|
|
* Result:
|
|
|
|
* handle of the open file or -1 if couldn't open any.
|
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
2012-01-04 16:34:05 +04:00
|
|
|
mc_mkstemps (vfs_path_t ** pname_vpath, const char *prefix, const char *suffix)
|
2012-01-04 12:44:35 +04:00
|
|
|
{
|
2012-10-08 17:35:03 +04:00
|
|
|
char *p1, *p2;
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
if (strchr (prefix, PATH_SEP) != NULL)
|
|
|
|
p1 = g_strdup (prefix);
|
2012-01-04 12:44:35 +04:00
|
|
|
else
|
|
|
|
{
|
2012-10-08 17:35:03 +04:00
|
|
|
/* Add prefix first to find the position of XXXXXX */
|
|
|
|
p1 = g_build_filename (mc_tmpdir (), prefix, (char *) NULL);
|
2012-01-04 12:44:35 +04:00
|
|
|
}
|
|
|
|
|
2012-10-08 17:35:03 +04:00
|
|
|
p2 = g_strconcat (p1, "XXXXXX", suffix, (char *) NULL);
|
|
|
|
g_free (p1);
|
2012-01-04 12:44:35 +04:00
|
|
|
|
2012-10-08 17:35:03 +04:00
|
|
|
fd = g_mkstemp (p2);
|
|
|
|
if (fd >= 0)
|
|
|
|
*pname_vpath = vfs_path_from_str (p2);
|
|
|
|
else
|
2012-01-04 12:44:35 +04:00
|
|
|
{
|
2012-10-08 17:35:03 +04:00
|
|
|
*pname_vpath = NULL;
|
|
|
|
fd = -1;
|
2012-01-04 12:44:35 +04:00
|
|
|
}
|
|
|
|
|
2012-10-08 17:35:03 +04:00
|
|
|
g_free (p2);
|
2012-01-04 12:44:35 +04:00
|
|
|
|
2012-10-08 17:35:03 +04:00
|
|
|
return fd;
|
2012-01-04 12:44:35 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* Return the directory where mc should keep its temporary files.
|
|
|
|
* This directory is (in Bourne shell terms) "${TMPDIR=/tmp}/mc-$USER"
|
|
|
|
* When called the first time, the directory is created if needed.
|
|
|
|
* The first call should be done early, since we are using fprintf()
|
|
|
|
* and not message() to report possible problems.
|
|
|
|
*/
|
|
|
|
|
|
|
|
const char *
|
|
|
|
mc_tmpdir (void)
|
|
|
|
{
|
2016-12-06 20:19:04 +03:00
|
|
|
static char buffer[PATH_MAX];
|
2012-03-16 14:53:34 +04:00
|
|
|
static const char *tmpdir = NULL;
|
2012-01-04 12:44:35 +04:00
|
|
|
const char *sys_tmp;
|
|
|
|
struct passwd *pwd;
|
|
|
|
struct stat st;
|
|
|
|
const char *error = NULL;
|
|
|
|
|
|
|
|
/* Check if already correctly initialized */
|
2019-09-21 14:01:15 +03:00
|
|
|
if (tmpdir != NULL && lstat (tmpdir, &st) == 0 && S_ISDIR (st.st_mode) &&
|
2012-01-04 12:44:35 +04:00
|
|
|
st.st_uid == getuid () && (st.st_mode & 0777) == 0700)
|
|
|
|
return tmpdir;
|
|
|
|
|
2021-02-13 16:24:41 +03:00
|
|
|
sys_tmp = getenv ("MC_TMPDIR");
|
2015-01-07 11:34:53 +03:00
|
|
|
if (sys_tmp == NULL || !IS_PATH_SEP (sys_tmp[0]))
|
2021-02-13 16:24:41 +03:00
|
|
|
{
|
|
|
|
sys_tmp = getenv ("TMPDIR");
|
|
|
|
if (sys_tmp == NULL || !IS_PATH_SEP (sys_tmp[0]))
|
|
|
|
sys_tmp = TMPDIR_DEFAULT;
|
|
|
|
}
|
2012-01-04 12:44:35 +04:00
|
|
|
|
|
|
|
pwd = getpwuid (getuid ());
|
2019-09-21 14:01:15 +03:00
|
|
|
if (pwd != NULL)
|
2012-01-04 12:44:35 +04:00
|
|
|
g_snprintf (buffer, sizeof (buffer), "%s/mc-%s", sys_tmp, pwd->pw_name);
|
|
|
|
else
|
|
|
|
g_snprintf (buffer, sizeof (buffer), "%s/mc-%lu", sys_tmp, (unsigned long) getuid ());
|
|
|
|
|
|
|
|
canonicalize_pathname (buffer);
|
|
|
|
|
2013-06-21 13:54:11 +04:00
|
|
|
/* Try to create directory */
|
|
|
|
if (mkdir (buffer, S_IRWXU) != 0)
|
2012-01-04 12:44:35 +04:00
|
|
|
{
|
2013-06-21 13:54:11 +04:00
|
|
|
if (errno == EEXIST && lstat (buffer, &st) == 0)
|
|
|
|
{
|
|
|
|
/* Sanity check for existing directory */
|
|
|
|
if (!S_ISDIR (st.st_mode))
|
|
|
|
error = _("%s is not a directory\n");
|
|
|
|
else if (st.st_uid != getuid ())
|
|
|
|
error = _("Directory %s is not owned by you\n");
|
|
|
|
else if (((st.st_mode & 0777) != 0700) && (chmod (buffer, 0700) != 0))
|
|
|
|
error = _("Cannot set correct permissions for directory %s\n");
|
|
|
|
}
|
|
|
|
else
|
2012-01-04 12:44:35 +04:00
|
|
|
{
|
|
|
|
fprintf (stderr,
|
|
|
|
_("Cannot create temporary directory %s: %s\n"),
|
|
|
|
buffer, unix_error_string (errno));
|
|
|
|
error = "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (error != NULL)
|
|
|
|
{
|
|
|
|
int test_fd;
|
2012-01-04 16:34:05 +04:00
|
|
|
char *fallback_prefix;
|
|
|
|
gboolean fallback_ok = FALSE;
|
|
|
|
vfs_path_t *test_vpath;
|
2012-01-04 12:44:35 +04:00
|
|
|
|
2019-09-21 14:01:15 +03:00
|
|
|
if (*error != '\0')
|
2012-01-04 12:44:35 +04:00
|
|
|
fprintf (stderr, error, buffer);
|
|
|
|
|
|
|
|
/* Test if sys_tmp is suitable for temporary files */
|
|
|
|
fallback_prefix = g_strdup_printf ("%s/mctest", sys_tmp);
|
2012-01-04 16:34:05 +04:00
|
|
|
test_fd = mc_mkstemps (&test_vpath, fallback_prefix, NULL);
|
2012-01-04 12:44:35 +04:00
|
|
|
g_free (fallback_prefix);
|
|
|
|
if (test_fd != -1)
|
|
|
|
{
|
|
|
|
close (test_fd);
|
2013-04-14 17:38:37 +04:00
|
|
|
test_fd = open (vfs_path_as_str (test_vpath), O_RDONLY);
|
2012-01-04 12:44:35 +04:00
|
|
|
if (test_fd != -1)
|
|
|
|
{
|
|
|
|
close (test_fd);
|
2013-04-14 17:38:37 +04:00
|
|
|
unlink (vfs_path_as_str (test_vpath));
|
2012-01-04 16:34:05 +04:00
|
|
|
fallback_ok = TRUE;
|
2012-01-04 12:44:35 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fallback_ok)
|
|
|
|
{
|
|
|
|
fprintf (stderr, _("Temporary files will be created in %s\n"), sys_tmp);
|
|
|
|
g_snprintf (buffer, sizeof (buffer), "%s", sys_tmp);
|
|
|
|
error = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fprintf (stderr, _("Temporary files will not be created\n"));
|
|
|
|
g_snprintf (buffer, sizeof (buffer), "%s", "/dev/null/");
|
|
|
|
}
|
|
|
|
|
2021-02-21 19:30:18 +03:00
|
|
|
vfs_path_free (test_vpath, TRUE);
|
2012-01-04 12:44:35 +04:00
|
|
|
fprintf (stderr, "%s\n", _("Press any key to continue..."));
|
|
|
|
getc (stdin);
|
|
|
|
}
|
|
|
|
|
|
|
|
tmpdir = buffer;
|
|
|
|
|
2019-09-21 14:01:15 +03:00
|
|
|
if (error == NULL)
|
2012-01-04 12:44:35 +04:00
|
|
|
g_setenv ("MC_TMPDIR", tmpdir, TRUE);
|
|
|
|
|
|
|
|
return tmpdir;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|