From a369aa0578f4a98f7b18a18ecc11d266b0f7fe71 Mon Sep 17 00:00:00 2001 From: lace <> Date: Sun, 22 Jan 2006 17:38:25 +0000 Subject: [PATCH] Workaround FUSE missing the generally broken Linux kernel charset support. - Captive FUSE client now no longer assumes client is using: utf8 - GLib (Gnome) filename charset rules are now followed. --- src/client/fuse/Makefile.am | 4 ++- src/client/fuse/op_chmod.c | 3 ++ src/client/fuse/op_getattr.c | 3 ++ src/client/fuse/op_mkdir.c | 3 ++ src/client/fuse/op_mknod.c | 3 ++ src/client/fuse/op_open.c | 3 ++ src/client/fuse/op_opendir.c | 3 ++ src/client/fuse/op_readdir.c | 6 +++- src/client/fuse/op_rename.c | 4 +++ src/client/fuse/op_rmdir.c | 3 ++ src/client/fuse/op_truncate.c | 3 ++ src/client/fuse/op_unlink.c | 3 ++ src/client/fuse/op_utime.c | 3 ++ src/client/fuse/utf8.c | 78 +++++++++++++++++++++++++++++++++++++++++++ src/client/fuse/utf8.h | 51 ++++++++++++++++++++++++++++ 15 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 src/client/fuse/utf8.c create mode 100644 src/client/fuse/utf8.h diff --git a/src/client/fuse/Makefile.am b/src/client/fuse/Makefile.am index 78fcb62..cf3d98a 100644 --- a/src/client/fuse/Makefile.am +++ b/src/client/fuse/Makefile.am @@ -63,7 +63,9 @@ mount_captive_SOURCES= \ capfuse_captive_file_info_object.c \ capfuse_captive_file_info_object.h \ main.c \ - main.h + main.h \ + utf8.c \ + utf8.h mount_captive_CFLAGS= $(GNOME_VFS_CFLAGS) $(LIBXML_CFLAGS) $(FUSE_CFLAGS) mount_captive_LDADD =$(captive_library) $(GNOME_VFS_LIBS) $(LIBXML_LIBS) $(FUSE_LIBS) $(INTLLIBS) mount_captive_LDFLAGS=$(READLINE_LDFLAGS) diff --git a/src/client/fuse/op_chmod.c b/src/client/fuse/op_chmod.c index 3813a67..80bac6e 100644 --- a/src/client/fuse/op_chmod.c +++ b/src/client/fuse/op_chmod.c @@ -30,6 +30,7 @@ #include "op_chmod.h" /* self */ #include "main.h" #include "gnomevfsresult.h" +#include "utf8.h" int op_chmod(const char *path,mode_t mode) @@ -45,6 +46,8 @@ CaptiveFileInfoObject *captive_file_info_object; && !S_ISDIR(mode)) return -EPERM; + path=CAPFUSE_FILENAME_TO_UTF8_ALLOCA(path); + /* Do not: GNOME_VFS_OPEN_WRITE * as we would get EPERM for setting back: chmod u+w */ diff --git a/src/client/fuse/op_getattr.c b/src/client/fuse/op_getattr.c index f72a8a9..7d1b88e 100644 --- a/src/client/fuse/op_getattr.c +++ b/src/client/fuse/op_getattr.c @@ -30,6 +30,7 @@ #include "main.h" #include "gnomevfsresult.h" #include "capfuse_captive_file_info_object.h" +#include "utf8.h" int op_getattr(const char *path,struct stat *buf) @@ -42,6 +43,8 @@ int errint; g_return_val_if_fail(path!=NULL,-EINVAL); g_return_val_if_fail(buf!=NULL,-EINVAL); + path=CAPFUSE_FILENAME_TO_UTF8_ALLOCA(path); + if (GNOME_VFS_OK!=(errvfsresult=captive_file_new_open(&captive_file_object,capfuse_captive_vfs_object,path,0))) return -gnomevfsresult_to_errno(errvfsresult); diff --git a/src/client/fuse/op_mkdir.c b/src/client/fuse/op_mkdir.c index a9a646f..ca3c81e 100644 --- a/src/client/fuse/op_mkdir.c +++ b/src/client/fuse/op_mkdir.c @@ -28,6 +28,7 @@ #include "op_mkdir.h" /* self */ #include "main.h" #include "gnomevfsresult.h" +#include "utf8.h" int op_mkdir(const char *path,mode_t mode) @@ -43,6 +44,8 @@ GnomeVFSResult errvfsresult; if (mode&S_IFMT) return -EPERM; + path=CAPFUSE_FILENAME_TO_UTF8_ALLOCA(path); + if (GNOME_VFS_OK!=(errvfsresult=captive_directory_new_make(&captive_directory_object,capfuse_captive_vfs_object, path, /* pathname */ mode))) /* perm */ diff --git a/src/client/fuse/op_mknod.c b/src/client/fuse/op_mknod.c index 79a445d..9e2d912 100644 --- a/src/client/fuse/op_mknod.c +++ b/src/client/fuse/op_mknod.c @@ -28,6 +28,7 @@ #include "op_mknod.h" /* self */ #include "main.h" #include "gnomevfsresult.h" +#include "utf8.h" int op_mknod(const char *path,mode_t mode,dev_t rdev) @@ -40,6 +41,8 @@ GnomeVFSResult errvfsresult; if (!S_ISREG(mode)) return -EPERM; + path=CAPFUSE_FILENAME_TO_UTF8_ALLOCA(path); + if (GNOME_VFS_OK!=(errvfsresult=captive_file_new_create(&captive_file_object,capfuse_captive_vfs_object, path, /* pathname */ 0, /* mode */ diff --git a/src/client/fuse/op_open.c b/src/client/fuse/op_open.c index 9f63503..4293bad 100644 --- a/src/client/fuse/op_open.c +++ b/src/client/fuse/op_open.c @@ -30,6 +30,7 @@ #include "op_open.h" /* self */ #include "main.h" #include "gnomevfsresult.h" +#include "utf8.h" int op_open(const char *path,struct fuse_file_info *fi) @@ -42,6 +43,8 @@ GnomeVFSResult errvfsresult; g_return_val_if_fail(sizeof(fi->fh)==sizeof(unsigned long),-EINVAL); g_return_val_if_fail(sizeof(fi->fh)>=sizeof(CaptiveFileObject *),-EINVAL); + path=CAPFUSE_FILENAME_TO_UTF8_ALLOCA(path); + if (GNOME_VFS_OK!=(errvfsresult=captive_file_new_open(&captive_file_object,capfuse_captive_vfs_object,path, GNOME_VFS_OPEN_RANDOM || (!(fi->flags&(O_RDONLY|O_RDWR)) ? 0 : GNOME_VFS_OPEN_READ) diff --git a/src/client/fuse/op_opendir.c b/src/client/fuse/op_opendir.c index 53370ac..8358a2b 100644 --- a/src/client/fuse/op_opendir.c +++ b/src/client/fuse/op_opendir.c @@ -27,6 +27,7 @@ #include "op_opendir.h" /* self */ #include "main.h" #include "gnomevfsresult.h" +#include "utf8.h" int op_opendir(const char *path,struct fuse_file_info *fi) @@ -39,6 +40,8 @@ GnomeVFSResult errvfsresult; g_return_val_if_fail(sizeof(fi->fh)==sizeof(unsigned long),-EINVAL); g_return_val_if_fail(sizeof(fi->fh)>=sizeof(CaptiveDirectoryObject *),-EINVAL); + path=CAPFUSE_FILENAME_TO_UTF8_ALLOCA(path); + if (GNOME_VFS_OK!=(errvfsresult=captive_directory_new_open(&captive_directory_object,capfuse_captive_vfs_object,path))) return -gnomevfsresult_to_errno(errvfsresult); diff --git a/src/client/fuse/op_readdir.c b/src/client/fuse/op_readdir.c index 16f920a..35d14a7 100644 --- a/src/client/fuse/op_readdir.c +++ b/src/client/fuse/op_readdir.c @@ -29,6 +29,7 @@ #include "main.h" #include "gnomevfsresult.h" #include "capfuse_captive_file_info_object.h" +#include "utf8.h" /* int (*fuse_fill_dir_t)(void *buf,const char *name,const struct stat *stbuf,off_t off); */ @@ -51,17 +52,20 @@ CaptiveFileInfoObject *captive_file_info_object; &captive_file_info_object))) { /* captive_file_info_object */ struct stat stat; int errint; +char *captive_file_info_object_name; errint=capfuse_captive_file_info_object_to_stat(&stat,captive_file_info_object); if (errint) { g_object_unref(captive_file_info_object); return errint; } + captive_file_info_object_name=capfuse_filename_from_utf8_malloc_errorchecking(captive_file_info_object->p.name); errint=(*fill_dir)( buf, /* buf; opaque */ - captive_file_info_object->p.name, /* name */ + (captive_file_info_object_name ? captive_file_info_object_name : captive_file_info_object->p.name), /* name */ &stat, /* stbuf */ 0); /* off; operation mode 1 - /(*readdir) */ + g_free(captive_file_info_object_name); /* may be NULL */ /* WARNING: (*fill_dir) needs: *captive_file_info_object->p.name */ g_object_unref(captive_file_info_object); if (errint) { diff --git a/src/client/fuse/op_rename.c b/src/client/fuse/op_rename.c index eb42cf8..4c46ee7 100644 --- a/src/client/fuse/op_rename.c +++ b/src/client/fuse/op_rename.c @@ -28,6 +28,7 @@ #include "op_rename.h" /* self */ #include "main.h" #include "gnomevfsresult.h" +#include "utf8.h" int op_rename(const char *oldpath,const char *newpath) @@ -38,6 +39,9 @@ GnomeVFSResult errvfsresult; g_return_val_if_fail(oldpath!=NULL,-EINVAL); g_return_val_if_fail(newpath!=NULL,-EINVAL); + oldpath=CAPFUSE_FILENAME_TO_UTF8_ALLOCA(oldpath); + newpath=CAPFUSE_FILENAME_TO_UTF8_ALLOCA(newpath); + if (GNOME_VFS_OK!=(errvfsresult=captive_file_new_open(&captive_file_object,capfuse_captive_vfs_object,oldpath, GNOME_VFS_OPEN_WRITE|GNOME_VFS_OPEN_RANDOM))) return -gnomevfsresult_to_errno(errvfsresult); diff --git a/src/client/fuse/op_rmdir.c b/src/client/fuse/op_rmdir.c index 5648ae8..55a4895 100644 --- a/src/client/fuse/op_rmdir.c +++ b/src/client/fuse/op_rmdir.c @@ -28,6 +28,7 @@ #include "op_rmdir.h" /* self */ #include "main.h" #include "gnomevfsresult.h" +#include "utf8.h" int op_rmdir(const char *path) @@ -37,6 +38,8 @@ GnomeVFSResult errvfsresult; g_return_val_if_fail(path!=NULL,-EINVAL); + path=CAPFUSE_FILENAME_TO_UTF8_ALLOCA(path); + if (GNOME_VFS_OK!=(errvfsresult=captive_directory_new_open(&captive_directory_object,capfuse_captive_vfs_object,path))) return -gnomevfsresult_to_errno(errvfsresult); diff --git a/src/client/fuse/op_truncate.c b/src/client/fuse/op_truncate.c index c8f5946..b71b061 100644 --- a/src/client/fuse/op_truncate.c +++ b/src/client/fuse/op_truncate.c @@ -29,6 +29,7 @@ #include "op_truncate.h" /* self */ #include "main.h" #include "gnomevfsresult.h" +#include "utf8.h" int op_truncate(const char *path,off_t size) @@ -39,6 +40,8 @@ GnomeVFSResult errvfsresult; g_return_val_if_fail(path!=NULL,-EINVAL); g_return_val_if_fail(size>=0,-EINVAL); + path=CAPFUSE_FILENAME_TO_UTF8_ALLOCA(path); + if (GNOME_VFS_OK!=(errvfsresult=captive_file_new_open(&captive_file_object,capfuse_captive_vfs_object,path, GNOME_VFS_OPEN_WRITE|GNOME_VFS_OPEN_RANDOM))) return -gnomevfsresult_to_errno(errvfsresult); diff --git a/src/client/fuse/op_unlink.c b/src/client/fuse/op_unlink.c index d100ee2..864a70a 100644 --- a/src/client/fuse/op_unlink.c +++ b/src/client/fuse/op_unlink.c @@ -28,6 +28,7 @@ #include "op_unlink.h" /* self */ #include "main.h" #include "gnomevfsresult.h" +#include "utf8.h" int op_unlink(const char *path) @@ -37,6 +38,8 @@ GnomeVFSResult errvfsresult; g_return_val_if_fail(path!=NULL,-EINVAL); + path=CAPFUSE_FILENAME_TO_UTF8_ALLOCA(path); + if (GNOME_VFS_OK!=(errvfsresult=captive_file_new_open(&captive_file_object,capfuse_captive_vfs_object,path, GNOME_VFS_OPEN_WRITE|GNOME_VFS_OPEN_RANDOM))) return -gnomevfsresult_to_errno(errvfsresult); diff --git a/src/client/fuse/op_utime.c b/src/client/fuse/op_utime.c index 22b9386..69a51df 100644 --- a/src/client/fuse/op_utime.c +++ b/src/client/fuse/op_utime.c @@ -32,6 +32,7 @@ #include "main.h" #include "gnomevfsresult.h" #include "capfuse_captive_file_info_object.h" +#include "utf8.h" int op_utime(const char *path,struct utimbuf *buf) @@ -45,6 +46,8 @@ CaptiveFileInfoObject *captive_file_info_object; g_return_val_if_fail(buf->actime!=0,-EINVAL); g_return_val_if_fail(buf->modtime!=0,-EINVAL); + path=CAPFUSE_FILENAME_TO_UTF8_ALLOCA(path); + if (GNOME_VFS_OK!=(errvfsresult=captive_file_new_open(&captive_file_object,capfuse_captive_vfs_object,path, GNOME_VFS_OPEN_WRITE|GNOME_VFS_OPEN_RANDOM))) return -gnomevfsresult_to_errno(errvfsresult); diff --git a/src/client/fuse/utf8.c b/src/client/fuse/utf8.c new file mode 100644 index 0000000..8c0ee73 --- /dev/null +++ b/src/client/fuse/utf8.c @@ -0,0 +1,78 @@ +/* $Id$ + * FUSE interface module utf8 conversions for libcaptive + * Copyright (C) 2003-2005 Jan Kratochvil + * + * This program 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; exactly version 2 of June 1991 is required + * + * This program 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "config.h" + +#include "utf8.h" /* self */ +#include +#include +#include +#include + + +char *capfuse_filename_to_utf8_malloc_errorchecking(const char *name) +{ +GError *error; +char *r; + + g_return_val_if_fail(name!=NULL,NULL); + + error=NULL; + r=g_filename_to_utf8( + name, /* opsysstring */ + -1, /* len; '\0'-terminated */ + NULL, /* bytes_read */ + NULL, /* bytes_written */ + &error); /* error */ + if (error) { + g_log(G_LOG_DOMAIN,G_LOG_LEVEL_WARNING, + _("captive-FUSE %s(): name=\"%s\": %s (see locale(7) and mount(8) environment variables)"), + "g_filename_to_utf8",name,error->message); + g_clear_error(&error); + } + return r; +} + + +char *capfuse_filename_from_utf8_malloc_errorchecking(const char *name) +{ +GError *error; +char *r; + + g_return_val_if_fail(name!=NULL,NULL); + + error=NULL; + r=g_filename_from_utf8( + name, /* utf8string */ + -1, /* len; '\0'-terminated */ + NULL, /* bytes_read */ + NULL, /* bytes_written */ + &error); /* error */ + if (error) { +const gchar *charset; + + g_get_charset(&charset); + g_log(G_LOG_DOMAIN,G_LOG_LEVEL_WARNING,"captive-FUSE %s(): name=\"%s\"; g_get_charset()=\"%s\", %s: %s", + "g_filename_from_utf8",name,charset, + _("see environment variables - locale(7), mount(8) and locale(1) commands \"locale\" and \"locale -a\""), + error->message); + g_clear_error(&error); + } + return r; +} diff --git a/src/client/fuse/utf8.h b/src/client/fuse/utf8.h new file mode 100644 index 0000000..7df8eb9 --- /dev/null +++ b/src/client/fuse/utf8.h @@ -0,0 +1,51 @@ +/* $Id$ + * Include file for FUSE interface module utf8 conversions for libcaptive + * Copyright (C) 2002-2005 Jan Kratochvil + * + * This program 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; exactly version 2 of June 1991 is required + * + * This program 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _CAPTIVE_CLIENT_FUSE_UTF8_H +#define _CAPTIVE_CLIENT_FUSE_UTF8_H 1 + + +#include + + +G_BEGIN_DECLS + +char *capfuse_filename_to_utf8_malloc_errorchecking(const char *name); +char *capfuse_filename_from_utf8_malloc_errorchecking(const char *name); + +#define CAPFUSE_FILENAME_TO_UTF8_ALLOCA(name) ({ \ + const char *_capfuse_filename_to_utf8_alloca_name=(name); \ + char *_capfuse_filename_to_utf8_alloca_r_malloc; \ + const char *_capfuse_filename_to_utf8_alloca_r; \ + \ + _capfuse_filename_to_utf8_alloca_r_malloc=capfuse_filename_to_utf8_malloc_errorchecking( \ + _capfuse_filename_to_utf8_alloca_name); \ + if (!_capfuse_filename_to_utf8_alloca_r_malloc) \ + _capfuse_filename_to_utf8_alloca_r=_capfuse_filename_to_utf8_alloca_name; \ + else { \ + _capfuse_filename_to_utf8_alloca_r=captive_strdup_alloca(_capfuse_filename_to_utf8_alloca_r_malloc); \ + g_free(_capfuse_filename_to_utf8_alloca_r_malloc); \ + } \ + _capfuse_filename_to_utf8_alloca_r; \ + }) + +G_END_DECLS + + +#endif /* _CAPTIVE_CLIENT_FUSE_UTF8_H */ -- 1.8.3.1