1
1

patches by Rostislav Beneš: mc-29-vfs

add support for filesystem, that use others encodings than mc (vfs). Now can be
encoding set only manually, but automatic detection is possible. Filename is
converted in mc_readdir and other function translate it back by vfs_translate
added menu etries encodnig in left and rigth menu (localization will be neede)
modified subshell.c to put subshell correct working directoy,
modified ext.c and execute.c to translate filename before running command
there could be one problem, vfs_translate_path does not use something like
path_magic function
Этот коммит содержится в:
Slava Zanko 2008-12-29 01:54:37 +02:00
родитель 75cf62902d
Коммит 1efbe4a18a
8 изменённых файлов: 451 добавлений и 43 удалений

Просмотреть файл

@ -1376,3 +1376,60 @@ toggle_listing_cmd (void)
set_basic_panel_listing_to (current, (p->list_type + 1) % LIST_TYPES);
}
/* add "#enc:encodning" to end of path */
/* if path end width a previous #enc:, only encoding is changed no additional
* #enc: is appended
* retun new string
*/
static char
*add_encoding_to_path (const char *path, const char *encoding)
{
char *result;
char *semi;
char *slash;
semi = g_strrstr (path, "#enc:");
if (semi != NULL) {
slash = strchr (semi, PATH_SEP);
if (slash != NULL) {
result = g_strconcat (path, "/#enc:", encoding, NULL);
} else {
*semi = 0;
result = g_strconcat (path, "/#enc:", encoding, NULL);
*semi = '#';
}
} else {
result = g_strconcat (path, "/#enc:", encoding, NULL);
}
return result;
}
static void
set_panel_encoding (WPanel *panel)
{
char *encoding;
char *cd_path;
encoding = input_dialog ("Encoding", "Select encoding", NULL);
if (encoding) {
cd_path = add_encoding_to_path (panel->cwd, encoding);
if (!do_panel_cd (MENU_PANEL, cd_path, 0))
message (1, MSG_ERROR, _(" Cannot chdir to %s "), cd_path);
g_free (cd_path);
}
}
void
encoding_cmd (void)
{
WPanel *panel;
if (!SELECTED_IS_PANEL)
return;
panel = MENU_PANEL;
set_panel_encoding (panel);
}

Просмотреть файл

@ -57,5 +57,6 @@ void quick_cmd_no_menu (void);
void info_cmd_no_menu (void);
void quick_view_cmd (void);
void toggle_listing_cmd (void);
void encoding_cmd (void);
#endif

Просмотреть файл

@ -30,6 +30,7 @@
#include "dialog.h"
#include "wtools.h"
#include "execute.h"
#include "../vfs/vfs.h"
static void
@ -342,7 +343,9 @@ execute_with_vfs_arg (const char *command, const char *filename)
/* Simplest case, this file is local */
if (!filename || vfs_file_is_local (filename)) {
do_execute (command, filename, EXECUTE_INTERNAL);
fn = vfs_canon_and_translate (filename);
do_execute (command, fn, EXECUTE_INTERNAL);
g_free (fn);
return;
}

Просмотреть файл

@ -62,6 +62,7 @@ static void
exec_extension (const char *filename, const char *data, int *move_dir,
int start_line)
{
char *fn;
char *file_name;
int cmd_file_fd;
FILE *cmd_file;
@ -174,10 +175,13 @@ exec_extension (const char *filename, const char *data, int *move_dir,
localmtime = mystat.st_mtime;
text = (*quote_func) (localcopy, 0);
} else {
text = (*quote_func) (filename, 0);
fn = vfs_canon_and_translate (filename);
text = (*quote_func) (fn, 0);
g_free (fn);
}
} else
} else {
text = expand_format (NULL, *data, !is_cd);
}
if (!is_cd)
fputs (text, cmd_file);
else {

Просмотреть файл

@ -810,6 +810,8 @@ static menu_entry LeftMenu[] = {
{' ', N_("&Sort order..."), NULL_HOTKEY, sort_cmd},
{' ', "", NULL_HOTKEY, 0},
{' ', N_("&Filter..."), NULL_HOTKEY, filter_cmd},
{' ', "",NULL_HOTKEY, 0},
{' ', N_("&Encoding..."), NULL_HOTKEY, encoding_cmd},
#ifdef USE_NETCODE
{' ', "", NULL_HOTKEY, 0},
#ifdef WITH_MCFS
@ -834,6 +836,8 @@ static menu_entry RightMenu[] = {
{' ', N_("&Sort order..."), NULL_HOTKEY, sort_cmd},
{' ', "", NULL_HOTKEY, 0},
{' ', N_("&Filter..."), NULL_HOTKEY, filter_cmd},
{' ', "",NULL_HOTKEY, 0},
{' ', N_("&Encoding..."), NULL_HOTKEY, encoding_cmd},
#ifdef USE_NETCODE
{' ', "", NULL_HOTKEY, 0},
#ifdef WITH_MCFS

Просмотреть файл

@ -530,6 +530,8 @@ static void init_raw_mode ()
int invoke_subshell (const char *command, int how, char **new_dir)
{
char *pcwd;
/* Make the MC terminal transparent */
tcsetattr (STDOUT_FILENO, TCSANOW, &raw_mode);
@ -560,8 +562,10 @@ int invoke_subshell (const char *command, int how, char **new_dir)
feed_subshell (how, FALSE);
if (new_dir && subshell_alive && strcmp (subshell_cwd, current_panel->cwd))
pcwd = vfs_translate_path_n (current_panel->cwd);
if (new_dir && subshell_alive && strcmp (subshell_cwd, pcwd))
*new_dir = subshell_cwd; /* Make MC change to the subshell's CWD */
g_free (pcwd);
/* Restart the subshell if it has died by SIGHUP, SIGQUIT, etc. */
while (!subshell_alive && !quit && use_subshell)
@ -752,15 +756,22 @@ subshell_name_quote (const char *s)
void
do_subshell_chdir (const char *directory, int do_update, int reset_prompt)
{
char *pcwd;
char *temp;
char *translate;
pcwd = vfs_translate_path_n (current_panel->cwd);
if (!
(subshell_state == INACTIVE
&& strcmp (subshell_cwd, current_panel->cwd))) {
&& strcmp (subshell_cwd, pcwd))) {
/* We have to repaint the subshell prompt if we read it from
* the main program. Please note that in the code after this
* if, the cd command that is sent will make the subshell
* repaint the prompt, so we don't have to paint it. */
if (do_update)
do_update_prompt ();
g_free (pcwd);
return;
}
@ -768,7 +779,9 @@ do_subshell_chdir (const char *directory, int do_update, int reset_prompt)
because we set "HISTCONTROL=ignorespace") */
write_all (subshell_pty, " cd ", 4);
if (*directory) {
char *temp = subshell_name_quote (directory);
translate = vfs_translate_path_n (directory);
if (translate) {
temp = subshell_name_quote (translate);
if (temp) {
write_all (subshell_pty, temp, strlen (temp));
g_free (temp);
@ -777,6 +790,10 @@ do_subshell_chdir (const char *directory, int do_update, int reset_prompt)
that we don't have memory to quote it. */
write_all (subshell_pty, ".", 1);
}
g_free (translate);
} else {
write_all (subshell_pty, ".", 1);
}
} else {
write_all (subshell_pty, "/", 1);
}
@ -786,7 +803,7 @@ do_subshell_chdir (const char *directory, int do_update, int reset_prompt)
feed_subshell (QUIETLY, FALSE);
if (subshell_alive) {
int bPathNotEq = strcmp (subshell_cwd, current_panel->cwd);
int bPathNotEq = strcmp (subshell_cwd, pcwd);
if (bPathNotEq && subshell_type == TCSH) {
char rp_subshell_cwd[PATH_MAX];
@ -795,17 +812,17 @@ do_subshell_chdir (const char *directory, int do_update, int reset_prompt)
char *p_subshell_cwd =
mc_realpath (subshell_cwd, rp_subshell_cwd);
char *p_current_panel_cwd =
mc_realpath (current_panel->cwd, rp_current_panel_cwd);
mc_realpath (pcwd, rp_current_panel_cwd);
if (p_subshell_cwd == NULL)
p_subshell_cwd = subshell_cwd;
if (p_current_panel_cwd == NULL)
p_current_panel_cwd = current_panel->cwd;
p_current_panel_cwd = pcwd;
bPathNotEq = strcmp (p_subshell_cwd, p_current_panel_cwd);
}
if (bPathNotEq && strcmp (current_panel->cwd, ".")) {
char *cwd = strip_password (g_strdup (current_panel->cwd), 1);
if (bPathNotEq && strcmp (pcwd, ".")) {
char *cwd = strip_password (g_strdup (pcwd), 1);
fprintf (stderr, _("Warning: Cannot change to %s.\n"), cwd);
g_free (cwd);
}
@ -814,6 +831,8 @@ do_subshell_chdir (const char *directory, int do_update, int reset_prompt)
if (reset_prompt)
prompt_pos = 0;
update_prompt = FALSE;
g_free (pcwd);
/* Make sure that MC never stores the CWD in a silly format */
/* like /usr////lib/../bin, or the strcmp() above will fail */
}

373
vfs/vfs.c
Просмотреть файл

@ -42,6 +42,7 @@
#include "../src/tty.h" /* enable/disable interrupt key */
#include "../src/wtools.h" /* message() */
#include "../src/main.h" /* print_vfs_message */
#include "../src/strutil.h"
#include "utilvfs.h"
#include "gc.h"
@ -64,10 +65,32 @@ struct vfs_openfile {
void *fsinfo;
};
struct vfs_dirinfo{
DIR *info;
str_conv_t converter;
};
static GSList *vfs_openfiles;
#define VFS_FIRST_HANDLE 100
static struct vfs_class *localfs_class;
static struct str_buffer *vfs_str_buffer;
static const char *supported_encodings[] = {
"UTF8",
"UTF-8",
"BIG5",
"ASCII",
"ISO8859",
"ISO-8859",
"ISO_8859",
"KOI8",
"CP852",
"CP866",
"CP125",
NULL
};
/* Create new VFS handle and put it to the list */
static int
@ -309,6 +332,161 @@ vfs_get_class (const char *pathname)
return vfs;
}
const char *
vfs_get_encoding (const char *path)
{
static char result[16];
char *work;
char *semi;
char *slash;
work = g_strdup (path);
semi = g_strrstr (work, "#enc:");
if (semi != NULL) {
semi+= 5 * sizeof (char);
slash = strchr (semi, PATH_SEP);
if (slash != NULL)
slash[0] = '\0';
g_strlcpy (result, semi, sizeof(result));
g_free (work);
return result;
} else {
g_free (work);
return NULL;
}
}
/* return if encoding can by used in vfs (is ascci full compactible) */
/* contains only a few encoding now */
static int
vfs_supported_enconding (const char *encoding) {
int t;
int result = 0;
for (t = 0; supported_encodings[t] != NULL; t++) {
result+= (g_ascii_strncasecmp (encoding, supported_encodings[t],
strlen (supported_encodings[t])) == 0);
}
return result;
}
/* 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
* defcnv - convertor, that is used as default, when path does not contain any
* #enc: subtring
* buffer - used to store result of translation
*/
static int
_vfs_translate_path (const char *path, int size,
str_conv_t defcnv, struct str_buffer *buffer)
{
const char *semi;
const char *ps;
const char *slash;
int state = 0;
static char encoding[16];
str_conv_t coder;
int ms;
if (size == 0) return 0;
size = (size > 0) ? size : strlen (path);
/* try found #end: */
semi = g_strrstr_len (path, size, "#enc:");
if (semi != NULL) {
/* first must be translated part before #enc: */
ms = semi - path;
/* remove '/' before #enc */
ps = str_cget_prev_char (semi);
if (ps[0] == PATH_SEP) ms = ps - path;
state = _vfs_translate_path (path, ms, defcnv, buffer);
if (state != 0) return state;
/* now can be translated part after #enc: */
semi+= 5;
slash = strchr (semi, PATH_SEP);
// ignore slashes after size;
if (slash - path >= size) slash = NULL;
ms = (slash != NULL) ? slash - semi : strlen (semi);
ms = min (ms, sizeof (encoding) - 1);
// limit encoding size (ms) to path size (size)
if (semi + ms > path + size) ms = path + size - semi;
memcpy (encoding, semi, ms);
encoding[ms] = '\0';
switch (vfs_supported_enconding (encoding)) {
case 1:
coder = str_crt_conv_to (encoding);
if (coder != (iconv_t) (-1)) {
if (slash != NULL) {
state = str_vfs_convert_to (coder, slash,
path + size - slash, buffer);
} else if (buffer->data[0] == '\0') {
/* exmaple "/#enc:utf-8" */
str_insert_char (PATH_SEP, buffer);
}
str_close_conv (coder);
return state;
} else {
errno = EINVAL;
return ESTR_FAILURE;
}
break;
default:
errno = EINVAL;
return ESTR_FAILURE;
}
} else {
/* path can be translated whole at once */
state = str_vfs_convert_to (defcnv, path, size, buffer);
return state;
}
return 0;
}
char *
vfs_translate_path (const char *path)
{
int state;
str_reset_buffer (vfs_str_buffer);
state = _vfs_translate_path (path, -1, str_cnv_from_term, vfs_str_buffer);
// strict version
//return (state == 0) ? vfs_str_buffer->data : NULL;
return (state != ESTR_FAILURE) ? vfs_str_buffer->data : NULL;
}
char *
vfs_translate_path_n (const char *path)
{
char *result;
result = vfs_translate_path (path);
return (result != NULL) ? g_strdup (result) : NULL;
}
char *
vfs_canon_and_translate (const char *path)
{
char *canon;
char *result;
canon = vfs_canon (path);
result = vfs_translate_path_n (canon);
g_free (canon);
return result;
}
static int
ferrno (struct vfs_class *vfs)
{
@ -323,7 +501,8 @@ mc_open (const char *filename, int flags, ...)
void *info;
va_list ap;
char *file = vfs_canon (filename);
char *file = vfs_canon_and_translate (filename);
if (file != NULL) {
struct vfs_class *vfs = vfs_get_class (file);
/* Get the mode flag */
@ -348,6 +527,7 @@ mc_open (const char *filename, int flags, ...)
}
return vfs_new_handle (vfs, info);
} else return -1;
}
@ -356,13 +536,15 @@ int mc_##name inarg \
{ \
struct vfs_class *vfs; \
int result; \
char *mpath = vfs_canon (path); \
char *mpath = vfs_canon_and_translate (path); \
if (mpath != NULL) { \
vfs = vfs_get_class (mpath); \
result = vfs->name ? (*vfs->name)callarg : -1; \
g_free (mpath); \
if (result == -1) \
errno = vfs->name ? ferrno (vfs) : E_NOTSUPP; \
return result; \
} else return -1; \
}
MC_NAMEOP (chmod, (const char *path, mode_t mode), (vfs, mpath, mode))
@ -370,11 +552,38 @@ MC_NAMEOP (chown, (const char *path, uid_t owner, gid_t group), (vfs, mpath, own
MC_NAMEOP (utime, (const char *path, struct utimbuf *times), (vfs, mpath, times))
MC_NAMEOP (readlink, (const char *path, char *buf, int bufsiz), (vfs, mpath, buf, bufsiz))
MC_NAMEOP (unlink, (const char *path), (vfs, mpath))
MC_NAMEOP (symlink, (const char *name1, const char *path), (vfs, name1, mpath))
MC_NAMEOP (mkdir, (const char *path, mode_t mode), (vfs, mpath, mode))
MC_NAMEOP (rmdir, (const char *path), (vfs, mpath))
MC_NAMEOP (mknod, (const char *path, mode_t mode, dev_t dev), (vfs, mpath, mode, dev))
int
mc_symlink (const char *name1, const char *path)
{
struct vfs_class *vfs;
int result;
char *mpath;
char *lpath;
char *tmp;
mpath = vfs_canon_and_translate (path);
if (mpath != NULL) {
tmp = g_strdup (name1);
lpath = vfs_translate_path_n (tmp);
g_free (tmp);
if (lpath != NULL) {
vfs = vfs_get_class (mpath);
result = vfs->symlink ? (*vfs->symlink) (vfs, lpath, mpath) : -1;
g_free (lpath);
if (result == -1)
errno = vfs->symlink ? ferrno (vfs) : E_NOTSUPP;
return result;
}
g_free (mpath);
}
return -1;
}
#define MC_HANDLEOP(name, inarg, callarg) \
ssize_t mc_##name inarg \
@ -399,9 +608,12 @@ int mc_##name (const char *fname1, const char *fname2) \
{ \
struct vfs_class *vfs; \
int result; \
char *name2, *name1 = vfs_canon (fname1); \
char *name2, *name1; \
name1 = vfs_canon_and_translate (fname1); \
if (name1 != NULL) { \
name2 = vfs_canon_and_translate (fname2); \
if (name2 != NULL) { \
vfs = vfs_get_class (name1); \
name2 = vfs_canon (fname2); \
if (vfs != vfs_get_class (name2)){ \
errno = EXDEV; \
g_free (name1); \
@ -414,6 +626,11 @@ int mc_##name (const char *fname1, const char *fname2) \
if (result == -1) \
errno = vfs->name ? ferrno (vfs) : E_NOTSUPP; \
return result; \
} else { \
g_free (name1); \
return -1; \
} \
} else return -1; \
}
MC_RENAMEOP (link)
@ -438,11 +655,13 @@ mc_setctl (const char *path, int ctlop, void *arg)
if (!path)
vfs_die("You don't want to pass NULL to mc_setctl.");
mpath = vfs_canon (path);
mpath = vfs_canon_and_translate (path);
if (mpath != NULL) {
vfs = vfs_get_class (mpath);
result = vfs->setctl ? (*vfs->setctl)(vfs, mpath, ctlop, arg) : 0;
g_free (mpath);
return result;
} else return -1;
}
int
@ -474,22 +693,43 @@ mc_opendir (const char *dirname)
int handle, *handlep;
void *info;
struct vfs_class *vfs;
char *canon;
char *dname;
struct vfs_dirinfo *dirinfo;
const char *encoding;
dname = vfs_canon (dirname);
vfs = vfs_get_class (dname);
canon = vfs_canon (dirname);
dname = vfs_translate_path_n (canon);
if (dname != NULL) {
vfs = vfs_get_class (dname);
info = vfs->opendir ? (*vfs->opendir)(vfs, dname) : NULL;
g_free (dname);
if (!info){
errno = vfs->opendir ? ferrno (vfs) : E_NOTSUPP;
g_free (canon);
return NULL;
}
handle = vfs_new_handle (vfs, info);
dirinfo = g_new (struct vfs_dirinfo, 1);
dirinfo->info = info;
encoding = vfs_get_encoding (canon);
g_free (canon);
dirinfo->converter = (encoding != NULL) ? str_crt_conv_from (encoding) :
str_cnv_from_term;
if (dirinfo->converter == (iconv_t) (-1)) dirinfo->converter =str_cnv_from_term;
handle = vfs_new_handle (vfs, dirinfo);
handlep = g_new (int, 1);
*handlep = handle;
return (DIR *) handlep;
} else {
g_free (canon);
return NULL;
}
}
struct dirent *
@ -497,7 +737,10 @@ mc_readdir (DIR *dirp)
{
int handle;
struct vfs_class *vfs;
struct dirent *result = NULL;
static struct dirent result;
struct dirent *entry = NULL;
struct vfs_dirinfo *dirinfo;
int state;
if (!dirp) {
errno = EFAULT;
@ -505,11 +748,21 @@ mc_readdir (DIR *dirp)
}
handle = *(int *) dirp;
vfs = vfs_op (handle);
if (vfs->readdir)
result = (*vfs->readdir) (vfs_info (handle));
if (!result)
errno = vfs->readdir ? ferrno (vfs) : E_NOTSUPP;
return result;
dirinfo = vfs_info (handle);
if (vfs->readdir) {
do {
entry = (*vfs->readdir) (dirinfo->info);
if (entry == NULL) return NULL;
str_reset_buffer (vfs_str_buffer);
state = str_vfs_convert_from (dirinfo->converter,
entry->d_name, vfs_str_buffer);
} while (state != 0);
memcpy (&result, entry, sizeof (struct dirent));
g_strlcpy (result.d_name, vfs_str_buffer->data, NAME_MAX + 1);
result.d_reclen = strlen (result.d_name);
}
if (entry == NULL) errno = vfs->readdir ? ferrno (vfs) : E_NOTSUPP;
return (entry != NULL) ? &result : NULL;
}
int
@ -518,9 +771,14 @@ mc_closedir (DIR *dirp)
int handle = *(int *) dirp;
struct vfs_class *vfs = vfs_op (handle);
int result;
struct vfs_dirinfo *dirinfo;
result = vfs->closedir ? (*vfs->closedir)(vfs_info (handle)) : -1;
dirinfo = vfs_info (handle);
if (dirinfo->converter != str_cnv_from_term) str_close_conv (dirinfo->converter);
result = vfs->closedir ? (*vfs->closedir)(dirinfo->info) : -1;
vfs_free_handle (handle);
g_free (dirinfo);
g_free (dirp);
return result;
}
@ -529,24 +787,37 @@ int mc_stat (const char *filename, struct stat *buf) {
struct vfs_class *vfs;
int result;
char *path;
path = vfs_canon (filename); vfs = vfs_get_class (path);
path = vfs_canon_and_translate (filename);
if (path != NULL) {
vfs = vfs_get_class (path);
result = vfs->stat ? (*vfs->stat) (vfs, path, buf) : -1;
g_free (path);
if (result == -1)
errno = vfs->name ? ferrno (vfs) : E_NOTSUPP;
return result;
} else return -1;
}
int mc_lstat (const char *filename, struct stat *buf) {
struct vfs_class *vfs;
int result;
char *path;
path = vfs_canon (filename); vfs = vfs_get_class (path);
path = vfs_canon_and_translate (filename);
if (path != NULL) {
vfs = vfs_get_class (path);
result = vfs->lstat ? (*vfs->lstat) (vfs, path, buf) : -1;
g_free (path);
if (result == -1)
errno = vfs->name ? ferrno (vfs) : E_NOTSUPP;
return result;
} else return -1;
}
int mc_fstat (int handle, struct stat *buf) {
@ -569,25 +840,40 @@ int mc_fstat (int handle, struct stat *buf) {
static const char *
_vfs_get_cwd (void)
{
char *p;
char *sys_cwd;
char *trans;
const char *encoding;
char *tmp;
int state;
struct stat my_stat, my_stat2;
if (!_vfs_get_class (current_dir)) {
p = g_get_current_dir ();
if (!p) /* One of the directories in the path is not readable */
trans = vfs_translate_path_n (current_dir); //add check if NULL
if (!_vfs_get_class (trans)) {
encoding = vfs_get_encoding (current_dir);
if (encoding == NULL) {
tmp = g_get_current_dir ();
if (tmp != NULL) { /* One of the directories in the path is not readable */
str_reset_buffer (vfs_str_buffer);
state = str_vfs_convert_from (str_cnv_from_term, tmp, vfs_str_buffer);
g_free (tmp);
sys_cwd = (state == 0) ? g_strdup (vfs_str_buffer->data) : NULL;
if (!sys_cwd)
return current_dir;
/* Otherwise check if it is O.K. to use the current_dir */
if (!cd_symlinks || mc_stat (p, &my_stat)
if (!cd_symlinks || mc_stat (sys_cwd, &my_stat)
|| mc_stat (current_dir, &my_stat2)
|| my_stat.st_ino != my_stat2.st_ino
|| my_stat.st_dev != my_stat2.st_dev) {
g_free (current_dir);
current_dir = p;
return p;
} /* Otherwise we return current_dir below */
g_free (p);
current_dir = sys_cwd;
return sys_cwd;
}/* Otherwise we return current_dir below */
}
}
}
g_free (trans);
return current_dir;
}
@ -682,22 +968,27 @@ int
mc_chdir (const char *path)
{
char *new_dir;
char *trans_dir;
struct vfs_class *old_vfs, *new_vfs;
vfsid old_vfsid;
int result;
new_dir = vfs_canon (path);
new_vfs = vfs_get_class (new_dir);
trans_dir = vfs_translate_path_n (new_dir);
if (trans_dir != NULL) {
new_vfs = vfs_get_class (trans_dir);
if (!new_vfs->chdir) {
g_free (new_dir);
g_free (trans_dir);
return -1;
}
result = (*new_vfs->chdir) (new_vfs, new_dir);
result = (*new_vfs->chdir) (new_vfs, trans_dir);
if (result == -1) {
errno = ferrno (new_vfs);
g_free (new_dir);
g_free (trans_dir);
return -1;
}
@ -720,7 +1011,12 @@ mc_chdir (const char *path)
*p = 0;
}
g_free (trans_dir);
return 0;
} else {
g_free (new_dir);
return -1;
}
}
/* Return 1 is the current VFS class is local */
@ -737,10 +1033,12 @@ vfs_file_class_flags (const char *filename)
struct vfs_class *vfs;
char *fname;
fname = vfs_canon (filename);
fname = vfs_canon_and_translate (filename);
if (fname != NULL) {
vfs = vfs_get_class (fname);
g_free (fname);
return vfs->flags;
} else return -1;
}
static char *
@ -792,7 +1090,10 @@ char *
mc_getlocalcopy (const char *pathname)
{
char *result;
char *path = vfs_canon (pathname);
char *path;
path = vfs_canon_and_translate (pathname);
if (path != NULL) {
struct vfs_class *vfs = vfs_get_class (path);
result = vfs->getlocalcopy ? (*vfs->getlocalcopy)(vfs, path) :
@ -801,6 +1102,7 @@ mc_getlocalcopy (const char *pathname)
if (!result)
errno = ferrno (vfs);
return result;
} else return NULL;
}
static int
@ -854,7 +1156,10 @@ int
mc_ungetlocalcopy (const char *pathname, const char *local, int has_changed)
{
int return_value = 0;
char *path = vfs_canon (pathname);
char *path;
path = vfs_canon_and_translate (pathname);
if (path != NULL) {
struct vfs_class *vfs = vfs_get_class (path);
return_value = vfs->ungetlocalcopy ?
@ -862,12 +1167,14 @@ mc_ungetlocalcopy (const char *pathname, const char *local, int has_changed)
mc_def_ungetlocalcopy (vfs, path, local, has_changed);
g_free (path);
return return_value;
} else return -1;
}
void
vfs_init (void)
{
vfs_str_buffer = str_get_buffer ();
/* localfs needs to be the first one */
init_localfs();
/* fallback value for vfs_get_class() */
@ -911,6 +1218,8 @@ vfs_shut (void)
(*vfs->done) (vfs);
g_slist_free (vfs_openfiles);
str_release_buffer (vfs_str_buffer);
}
/*

Просмотреть файл

@ -10,6 +10,17 @@ char *mc_get_current_wd (char *buffer, int bufsize);
char *vfs_get_current_dir (void);
int vfs_current_is_local (void);
int vfs_file_is_local (const char *filename);
/* translate path back to terminal encoding, remove all #enc:
* every invalid character is replaced with question mark
* return static buffer */
char *vfs_translate_path (const char *path);
/* return new string */
char *vfs_translate_path_n (const char *path);
/* return encoding after last #enc: or NULL, if part does not contain #enc:
* return static buffer */
const char *vfs_get_encoding (const char *path);
// canonize and translate path, return new string */
char *vfs_canon_and_translate (const char *path);
/* Only the routines outside of the VFS module need the emulation macros */