--- fuse-2.6.1/include/fuse_common.h.charset 2006-10-10 14:34:22.000000000 +0300 +++ fuse-2.6.1/include/fuse_common.h 2006-12-30 23:15:18.000000000 +0200 @@ -158,7 +158,7 @@ * @return 0 on success, -1 on failure */ int fuse_parse_cmdline(struct fuse_args *args, char **mountpoint, - int *multithreaded, int *foreground); + int *multithreaded, int *foreground, char **charset); int fuse_daemonize(int foreground); --- fuse-2.6.1/lib/fuse_i.h.charset 2006-09-06 13:36:11.000000000 +0300 +++ fuse-2.6.1/lib/fuse_i.h 2006-12-30 23:15:18.000000000 +0200 @@ -34,3 +34,9 @@ void fuse_kern_unmount_compat22(const char *mountpoint); void fuse_kern_unmount(const char *mountpoint, int fd); int fuse_kern_mount(const char *mountpoint, struct fuse_args *args); + +int fuse_iconv_open(const char *charset, int debug); +char *fuse_iconv_from(const char *input); +char *fuse_iconv_to(const char *input); +void fuse_iconv_close(void); + --- fuse-2.6.1/lib/fuse.c.charset 2006-11-06 13:53:12.000000000 +0200 +++ fuse-2.6.1/lib/fuse.c 2006-12-30 23:15:18.000000000 +0200 @@ -908,10 +908,11 @@ struct fuse_entry_param e; char *path; int err; + char *name2 = fuse_iconv_to(name); err = -ENOENT; pthread_rwlock_rdlock(&f->tree_lock); - path = get_path_name(f, parent, name); + path = get_path_name(f, parent, name2); if (path != NULL) { if (f->conf.debug) { printf("LOOKUP %s\n", path); @@ -919,7 +920,7 @@ } err = -ENOSYS; if (f->op.getattr) { - err = lookup_path(f, req, parent, name, path, &e, NULL); + err = lookup_path(f, req, parent, name2, path, &e, NULL); if (err == -ENOENT && f->conf.negative_timeout != 0.0) { e.ino = 0; e.entry_timeout = f->conf.negative_timeout; @@ -929,6 +930,7 @@ free(path); } pthread_rwlock_unlock(&f->tree_lock); + free(name2); reply_entry(req, &e, err); } @@ -1796,6 +1798,7 @@ { struct stat stbuf; size_t newlen; + char *name2 = fuse_iconv_from(name); if (statp) stbuf = *statp; @@ -1818,24 +1821,28 @@ if (off) { if (extend_contents(dh, dh->needlen) == -1) - return 1; + goto out_err; dh->filled = 0; newlen = dh->len + fuse_add_direntry(dh->req, dh->contents + dh->len, - dh->needlen - dh->len, name, + dh->needlen - dh->len, name2, &stbuf, off); if (newlen > dh->needlen) - return 1; + goto out_err; } else { - newlen = dh->len + fuse_add_direntry(dh->req, NULL, 0, name, NULL, 0); + newlen = dh->len + fuse_add_direntry(dh->req, NULL, 0, name2, NULL, 0); if (extend_contents(dh, newlen) == -1) - return 1; + goto out_err; fuse_add_direntry(dh->req, dh->contents + dh->len, dh->size - dh->len, - name, &stbuf, newlen); + name2, &stbuf, newlen); } dh->len = newlen; + free(name2); return 0; +out_err: + free(name2); + return 1; } static int fill_dir(void *buf, const char *name, const struct stat *stbuf, --- fuse-2.6.1/lib/Makefile.am.charset 2006-12-01 13:59:21.000000000 +0200 +++ fuse-2.6.1/lib/Makefile.am 2006-12-30 23:15:18.000000000 +0200 @@ -14,6 +14,7 @@ libfuse_la_SOURCES = \ fuse.c \ fuse_i.h \ + fuse_iconv.c \ fuse_kern_chan.c \ fuse_loop.c \ fuse_loop_mt.c \ --- /dev/null 2006-12-26 10:48:59.878695230 +0200 +++ fuse-2.6.1/lib/fuse_iconv.c 2006-12-30 23:15:18.000000000 +0200 @@ -0,0 +1,100 @@ +/* + */ + +#include "fuse_i.h" + +#include +#include +#include +#include +#include + +static iconv_t conv_ft = (iconv_t) -1; +static iconv_t conv_tf = (iconv_t) -1; + +/* Local functions */ +static char *name_conv(iconv_t cd, const char *input); +static const char *get_current_charmap(void); + +/* ========================================================== */ +static char *name_conv(iconv_t cd, const char *input) { + size_t insize = strlen(input); + size_t outsize = insize * 6; /* enought for UTF-8 */ + char *output, *inptr, *outptr; + size_t nconv; + + if (cd == (iconv_t) -1) + return strdup(input); + + output = calloc(outsize + 1, sizeof(*output)); + + outptr = output; + inptr = (char *) input; + + nconv = iconv(cd, &inptr, &insize, &outptr, &outsize); + + if (nconv == (size_t) -1) { + free(output); + return strdup(input); + } + + return output; +} + +static const char *get_current_charmap(void) +{ + static int init = -1; + static char *charmap = NULL; + + if (init == -1) { + char *lc_ctype = setlocale (LC_CTYPE, ""); + charmap = nl_langinfo (CODESET); + setlocale (LC_CTYPE, lc_ctype); + init = 0; + } + return charmap; +} + +/* ========================================================== */ +int fuse_iconv_open(const char *charset, int debug) +{ + const char *lang = get_current_charmap(); + + if (lang && charset && (strcasecmp(lang, charset) != 0)) { + conv_ft = iconv_open(lang, charset); + if (conv_ft != (iconv_t) -1) { + conv_tf = iconv_open(charset, lang); + if (conv_tf == (iconv_t) -1) { + iconv_close(conv_ft); + conv_ft = (iconv_t) -1; + return -1; + } else { + if (debug) { + printf("ICONV %s <-> %s\n", lang, charset); + fflush(stdout); + } + } + } + } + return 0; +} + +char *fuse_iconv_from(const char *input) +{ + return name_conv(conv_ft, input); +} + +char *fuse_iconv_to(const char *input) +{ + return name_conv(conv_tf, input); +} + +void fuse_iconv_close(void) +{ + if (conv_ft != (iconv_t) -1) + iconv_close(conv_ft); + + if (conv_tf != (iconv_t) -1) + iconv_close(conv_tf); +} + --- fuse-2.6.1/lib/helper.c.charset 2006-11-11 11:39:25.000000000 +0200 +++ fuse-2.6.1/lib/helper.c 2006-12-30 23:15:18.000000000 +0200 @@ -24,6 +24,7 @@ KEY_HELP, KEY_HELP_NOHEADER, KEY_VERSION, + KEY_CHARSET, }; struct helper_opts { @@ -31,6 +32,7 @@ int foreground; int fsname; char *mountpoint; + char *charset; }; #define FUSE_HELPER_OPT(t, p) { t, offsetof(struct helper_opts, p), 1 } @@ -41,6 +43,7 @@ FUSE_HELPER_OPT("-f", foreground), FUSE_HELPER_OPT("-s", singlethread), FUSE_HELPER_OPT("fsname=", fsname), + FUSE_HELPER_OPT("charset=", charset), FUSE_OPT_KEY("-h", KEY_HELP), FUSE_OPT_KEY("--help", KEY_HELP), @@ -50,6 +53,7 @@ FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP), FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP), FUSE_OPT_KEY("fsname=", FUSE_OPT_KEY_KEEP), + FUSE_OPT_KEY("charset=", KEY_CHARSET), FUSE_OPT_END }; @@ -72,6 +76,7 @@ " -d -o debug enable debug output (implies -f)\n" " -f foreground operation\n" " -s disable multi-threaded operation\n" + " -o charset=CHARSET assume filename encoding\n" "\n" ); } @@ -99,6 +104,16 @@ helper_version(); return 1; + case KEY_CHARSET: { + char *charset = strchr(arg, '='); + if (charset == NULL) + charset = arg; + else + charset++; + hopts->charset = strdup(charset); + return 0; + } + case FUSE_OPT_KEY_NONOPT: if (!hopts->mountpoint) { char mountpoint[PATH_MAX]; @@ -139,7 +154,7 @@ } int fuse_parse_cmdline(struct fuse_args *args, char **mountpoint, - int *multithreaded, int *foreground) + int *multithreaded, int *foreground, char **charset) { int res; struct helper_opts hopts; @@ -159,6 +174,11 @@ else free(hopts.mountpoint); + if (charset) + *charset = hopts.charset; + else + free(hopts.charset); + if (multithreaded) *multithreaded = !hopts.singlethread; if (foreground) @@ -167,6 +187,7 @@ err: free(hopts.mountpoint); + free(hopts.charset); return -1; } @@ -237,8 +258,9 @@ struct fuse *fuse; int foreground; int res; + char *charset; - res = fuse_parse_cmdline(&args, mountpoint, multithreaded, &foreground); + res = fuse_parse_cmdline(&args, mountpoint, multithreaded, &foreground, &charset); if (res == -1) return NULL; @@ -264,6 +286,7 @@ if (fd) *fd = fuse_chan_fd(ch); + fuse_iconv_open(charset, foreground); return fuse; err_unmount: @@ -289,6 +312,7 @@ struct fuse_chan *ch = fuse_session_next_chan(se, NULL); fuse_remove_signal_handlers(se); fuse_unmount_common(mountpoint, ch); + fuse_iconv_close(); fuse_destroy(fuse); free(mountpoint); } --- fuse-2.6.1/example/hello_ll.c.charset 2006-10-01 15:35:44.000000000 +0300 +++ fuse-2.6.1/example/hello_ll.c 2006-12-30 23:16:46.000000000 +0200 @@ -157,7 +157,7 @@ char *mountpoint; int err = -1; - if (fuse_parse_cmdline(&args, &mountpoint, NULL, NULL) != -1 && + if (fuse_parse_cmdline(&args, &mountpoint, NULL, NULL, NULL) != -1 && (ch = fuse_mount(mountpoint, &args)) != NULL) { struct fuse_session *se;