9#include <fuse_config.h> 
   37static struct iconv *iconv_get(
void)
 
   42static int iconv_convpath(
struct iconv *ic, 
const char *path, 
char **newpathp,
 
   58        pathlen = strlen(path);
 
   59        newpathlen = pathlen * 4;
 
   60        newpath = malloc(newpathlen + 1);
 
   66        pthread_mutex_lock(&ic->lock);
 
   68                res = iconv(fromfs ? ic->fromfs : ic->tofs, (char **) &path,
 
   70                if (res == (
size_t) -1) {
 
   78                        inc = (pathlen + 1) * 4;
 
   81                        tmp = realloc(newpath, newpathlen + 1);
 
   90        } 
while (res == (
size_t) -1);
 
   91        pthread_mutex_unlock(&ic->lock);
 
   97        iconv(fromfs ? ic->fromfs : ic->tofs, NULL, NULL, NULL, NULL);
 
   98        pthread_mutex_unlock(&ic->lock);
 
  103static int iconv_getattr(
const char *path, 
struct stat *stbuf,
 
  106        struct iconv *ic = iconv_get();
 
  108        int err = iconv_convpath(ic, path, &newpath, 0);
 
  110                err = fuse_fs_getattr(ic->next, newpath, stbuf, fi);
 
  116static int iconv_access(
const char *path, 
int mask)
 
  118        struct iconv *ic = iconv_get();
 
  120        int err = iconv_convpath(ic, path, &newpath, 0);
 
  122                err = fuse_fs_access(ic->next, newpath, mask);
 
  128static int iconv_readlink(
const char *path, 
char *buf, 
size_t size)
 
  130        struct iconv *ic = iconv_get();
 
  132        int err = iconv_convpath(ic, path, &newpath, 0);
 
  134                err = fuse_fs_readlink(ic->next, newpath, buf, size);
 
  137                        err = iconv_convpath(ic, buf, &newlink, 1);
 
  139                                strncpy(buf, newlink, size - 1);
 
  140                                buf[size - 1] = 
'\0';
 
  149static int iconv_opendir(
const char *path, 
struct fuse_file_info *fi)
 
  151        struct iconv *ic = iconv_get();
 
  153        int err = iconv_convpath(ic, path, &newpath, 0);
 
  155                err = fuse_fs_opendir(ic->next, newpath, fi);
 
  161static int iconv_dir_fill(
void *buf, 
const char *name,
 
  162                          const struct stat *stbuf, off_t off,
 
  165        struct iconv_dh *dh = buf;
 
  168        if (iconv_convpath(dh->ic, name, &newname, 1) == 0) {
 
  169                res = dh->prev_filler(dh->prev_buf, newname, stbuf, off, flags);
 
  175static int iconv_readdir(
const char *path, 
void *buf, 
fuse_fill_dir_t filler,
 
  179        struct iconv *ic = iconv_get();
 
  181        int err = iconv_convpath(ic, path, &newpath, 0);
 
  186                dh.prev_filler = filler;
 
  187                err = fuse_fs_readdir(ic->next, newpath, &dh, iconv_dir_fill,
 
  194static int iconv_releasedir(
const char *path, 
struct fuse_file_info *fi)
 
  196        struct iconv *ic = iconv_get();
 
  198        int err = iconv_convpath(ic, path, &newpath, 0);
 
  200                err = fuse_fs_releasedir(ic->next, newpath, fi);
 
  206static int iconv_mknod(
const char *path, mode_t mode, dev_t rdev)
 
  208        struct iconv *ic = iconv_get();
 
  210        int err = iconv_convpath(ic, path, &newpath, 0);
 
  212                err = fuse_fs_mknod(ic->next, newpath, mode, rdev);
 
  218static int iconv_mkdir(
const char *path, mode_t mode)
 
  220        struct iconv *ic = iconv_get();
 
  222        int err = iconv_convpath(ic, path, &newpath, 0);
 
  224                err = fuse_fs_mkdir(ic->next, newpath, mode);
 
  230static int iconv_unlink(
const char *path)
 
  232        struct iconv *ic = iconv_get();
 
  234        int err = iconv_convpath(ic, path, &newpath, 0);
 
  236                err = fuse_fs_unlink(ic->next, newpath);
 
  242static int iconv_rmdir(
const char *path)
 
  244        struct iconv *ic = iconv_get();
 
  246        int err = iconv_convpath(ic, path, &newpath, 0);
 
  248                err = fuse_fs_rmdir(ic->next, newpath);
 
  254static int iconv_symlink(
const char *from, 
const char *to)
 
  256        struct iconv *ic = iconv_get();
 
  259        int err = iconv_convpath(ic, from, &newfrom, 0);
 
  261                err = iconv_convpath(ic, to, &newto, 0);
 
  263                        err = fuse_fs_symlink(ic->next, newfrom, newto);
 
  271static int iconv_rename(
const char *from, 
const char *to, 
unsigned int flags)
 
  273        struct iconv *ic = iconv_get();
 
  276        int err = iconv_convpath(ic, from, &newfrom, 0);
 
  278                err = iconv_convpath(ic, to, &newto, 0);
 
  280                        err = fuse_fs_rename(ic->next, newfrom, newto, flags);
 
  288static int iconv_link(
const char *from, 
const char *to)
 
  290        struct iconv *ic = iconv_get();
 
  293        int err = iconv_convpath(ic, from, &newfrom, 0);
 
  295                err = iconv_convpath(ic, to, &newto, 0);
 
  297                        err = fuse_fs_link(ic->next, newfrom, newto);
 
  305static int iconv_chmod(
const char *path, mode_t mode,
 
  308        struct iconv *ic = iconv_get();
 
  310        int err = iconv_convpath(ic, path, &newpath, 0);
 
  312                err = fuse_fs_chmod(ic->next, newpath, mode, fi);
 
  318static int iconv_chown(
const char *path, uid_t uid, gid_t gid,
 
  321        struct iconv *ic = iconv_get();
 
  323        int err = iconv_convpath(ic, path, &newpath, 0);
 
  325                err = fuse_fs_chown(ic->next, newpath, uid, gid, fi);
 
  331static int iconv_truncate(
const char *path, off_t size,
 
  334        struct iconv *ic = iconv_get();
 
  336        int err = iconv_convpath(ic, path, &newpath, 0);
 
  338                err = fuse_fs_truncate(ic->next, newpath, size, fi);
 
  344static int iconv_utimens(
const char *path, 
const struct timespec ts[2],
 
  347        struct iconv *ic = iconv_get();
 
  349        int err = iconv_convpath(ic, path, &newpath, 0);
 
  351                err = fuse_fs_utimens(ic->next, newpath, ts, fi);
 
  357static int iconv_create(
const char *path, mode_t mode,
 
  360        struct iconv *ic = iconv_get();
 
  362        int err = iconv_convpath(ic, path, &newpath, 0);
 
  364                err = fuse_fs_create(ic->next, newpath, mode, fi);
 
  370static int iconv_open_file(
const char *path, 
struct fuse_file_info *fi)
 
  372        struct iconv *ic = iconv_get();
 
  374        int err = iconv_convpath(ic, path, &newpath, 0);
 
  376                err = fuse_fs_open(ic->next, newpath, fi);
 
  382static int iconv_read_buf(
const char *path, 
struct fuse_bufvec **bufp,
 
  385        struct iconv *ic = iconv_get();
 
  387        int err = iconv_convpath(ic, path, &newpath, 0);
 
  389                err = fuse_fs_read_buf(ic->next, newpath, bufp, size, offset, fi);
 
  395static int iconv_write_buf(
const char *path, 
struct fuse_bufvec *buf,
 
  398        struct iconv *ic = iconv_get();
 
  400        int err = iconv_convpath(ic, path, &newpath, 0);
 
  402                err = fuse_fs_write_buf(ic->next, newpath, buf, offset, fi);
 
  408static int iconv_statfs(
const char *path, 
struct statvfs *stbuf)
 
  410        struct iconv *ic = iconv_get();
 
  412        int err = iconv_convpath(ic, path, &newpath, 0);
 
  414                err = fuse_fs_statfs(ic->next, newpath, stbuf);
 
  420static int iconv_flush(
const char *path, 
struct fuse_file_info *fi)
 
  422        struct iconv *ic = iconv_get();
 
  424        int err = iconv_convpath(ic, path, &newpath, 0);
 
  426                err = fuse_fs_flush(ic->next, newpath, fi);
 
  432static int iconv_release(
const char *path, 
struct fuse_file_info *fi)
 
  434        struct iconv *ic = iconv_get();
 
  436        int err = iconv_convpath(ic, path, &newpath, 0);
 
  438                err = fuse_fs_release(ic->next, newpath, fi);
 
  444static int iconv_fsync(
const char *path, 
int isdatasync,
 
  447        struct iconv *ic = iconv_get();
 
  449        int err = iconv_convpath(ic, path, &newpath, 0);
 
  451                err = fuse_fs_fsync(ic->next, newpath, isdatasync, fi);
 
  457static int iconv_fsyncdir(
const char *path, 
int isdatasync,
 
  460        struct iconv *ic = iconv_get();
 
  462        int err = iconv_convpath(ic, path, &newpath, 0);
 
  464                err = fuse_fs_fsyncdir(ic->next, newpath, isdatasync, fi);
 
  470static int iconv_setxattr(
const char *path, 
const char *name,
 
  471                          const char *value, 
size_t size, 
int flags)
 
  473        struct iconv *ic = iconv_get();
 
  475        int err = iconv_convpath(ic, path, &newpath, 0);
 
  477                err = fuse_fs_setxattr(ic->next, newpath, name, value, size,
 
  484static int iconv_getxattr(
const char *path, 
const char *name, 
char *value,
 
  487        struct iconv *ic = iconv_get();
 
  489        int err = iconv_convpath(ic, path, &newpath, 0);
 
  491                err = fuse_fs_getxattr(ic->next, newpath, name, value, size);
 
  497static int iconv_listxattr(
const char *path, 
char *list, 
size_t size)
 
  499        struct iconv *ic = iconv_get();
 
  501        int err = iconv_convpath(ic, path, &newpath, 0);
 
  503                err = fuse_fs_listxattr(ic->next, newpath, list, size);
 
  509static int iconv_removexattr(
const char *path, 
const char *name)
 
  511        struct iconv *ic = iconv_get();
 
  513        int err = iconv_convpath(ic, path, &newpath, 0);
 
  515                err = fuse_fs_removexattr(ic->next, newpath, name);
 
  521static int iconv_lock(
const char *path, 
struct fuse_file_info *fi, 
int cmd,
 
  524        struct iconv *ic = iconv_get();
 
  526        int err = iconv_convpath(ic, path, &newpath, 0);
 
  528                err = fuse_fs_lock(ic->next, newpath, fi, cmd, lock);
 
  534static int iconv_flock(
const char *path, 
struct fuse_file_info *fi, 
int op)
 
  536        struct iconv *ic = iconv_get();
 
  538        int err = iconv_convpath(ic, path, &newpath, 0);
 
  540                err = fuse_fs_flock(ic->next, newpath, fi, op);
 
  546static int iconv_bmap(
const char *path, 
size_t blocksize, uint64_t *idx)
 
  548        struct iconv *ic = iconv_get();
 
  550        int err = iconv_convpath(ic, path, &newpath, 0);
 
  552                err = fuse_fs_bmap(ic->next, newpath, blocksize, idx);
 
  558static off_t iconv_lseek(
const char *path, off_t off, 
int whence,
 
  561        struct iconv *ic = iconv_get();
 
  563        int res = iconv_convpath(ic, path, &newpath, 0);
 
  565                res = fuse_fs_lseek(ic->next, newpath, off, whence, fi);
 
  574        struct iconv *ic = iconv_get();
 
  575        fuse_fs_init(ic->next, conn, cfg);
 
  581static void iconv_destroy(
void *data)
 
  583        struct iconv *ic = data;
 
  584        fuse_fs_destroy(ic->next);
 
  585        iconv_close(ic->tofs);
 
  586        iconv_close(ic->fromfs);
 
  587        pthread_mutex_destroy(&ic->lock);
 
  596        .getattr        = iconv_getattr,
 
  597        .access         = iconv_access,
 
  598        .readlink       = iconv_readlink,
 
  599        .opendir        = iconv_opendir,
 
  600        .readdir        = iconv_readdir,
 
  601        .releasedir     = iconv_releasedir,
 
  602        .mknod          = iconv_mknod,
 
  603        .mkdir          = iconv_mkdir,
 
  604        .symlink        = iconv_symlink,
 
  605        .unlink         = iconv_unlink,
 
  606        .rmdir          = iconv_rmdir,
 
  607        .rename         = iconv_rename,
 
  609        .chmod          = iconv_chmod,
 
  610        .chown          = iconv_chown,
 
  611        .truncate       = iconv_truncate,
 
  612        .utimens        = iconv_utimens,
 
  613        .create         = iconv_create,
 
  614        .open           = iconv_open_file,
 
  615        .read_buf       = iconv_read_buf,
 
  616        .write_buf      = iconv_write_buf,
 
  617        .statfs         = iconv_statfs,
 
  618        .flush          = iconv_flush,
 
  619        .release        = iconv_release,
 
  620        .fsync          = iconv_fsync,
 
  621        .fsyncdir       = iconv_fsyncdir,
 
  622        .setxattr       = iconv_setxattr,
 
  623        .getxattr       = iconv_getxattr,
 
  624        .listxattr      = iconv_listxattr,
 
  625        .removexattr    = iconv_removexattr,
 
  627        .flock          = iconv_flock,
 
  629        .lseek          = iconv_lseek,
 
  632static const struct fuse_opt iconv_opts[] = {
 
  635        { 
"from_code=%s", offsetof(
struct iconv, from_code), 0 },
 
  636        { 
"to_code=%s", offsetof(
struct iconv, to_code), 1 },
 
  640static void iconv_help(
void)
 
  643        const char *old = setlocale(LC_CTYPE, 
"");
 
  645        charmap = strdup(nl_langinfo(CODESET));
 
  647                setlocale(LC_CTYPE, old);
 
  652"    -o from_code=CHARSET   original encoding of file names (default: UTF-8)\n" 
  653"    -o to_code=CHARSET     new encoding of the file names (default: %s)\n",
 
  658static int iconv_opt_proc(
void *data, 
const char *arg, 
int key,
 
  661        (void) data; (void) arg; (void) outargs;
 
  671static struct fuse_fs *iconv_new(
struct fuse_args *args,
 
  672                                 struct fuse_fs *next[])
 
  676        const char *old = NULL;
 
  680        ic = calloc(1, 
sizeof(
struct iconv));
 
  682                fuse_log(FUSE_LOG_ERR, 
"fuse-iconv: memory allocation failed\n");
 
  689        if (!next[0] || next[1]) {
 
  690                fuse_log(FUSE_LOG_ERR, 
"fuse-iconv: exactly one next filesystem required\n");
 
  694        from = ic->from_code ? ic->from_code : 
"UTF-8";
 
  695        to = ic->to_code ? ic->to_code : 
"";
 
  698                old = setlocale(LC_CTYPE, 
"");
 
  699        ic->tofs = iconv_open(from, to);
 
  700        if (ic->tofs == (iconv_t) -1) {
 
  701                fuse_log(FUSE_LOG_ERR, 
"fuse-iconv: cannot convert from %s to %s\n",
 
  705        ic->fromfs = iconv_open(to, from);
 
  706        if (ic->tofs == (iconv_t) -1) {
 
  707                fuse_log(FUSE_LOG_ERR, 
"fuse-iconv: cannot convert from %s to %s\n",
 
  709                goto out_iconv_close_to;
 
  712                setlocale(LC_CTYPE, old);
 
  717        fs = 
fuse_fs_new(&iconv_oper, 
sizeof(iconv_oper), ic);
 
  719                goto out_iconv_close_from;
 
  724        iconv_close(ic->fromfs);
 
  726        iconv_close(ic->tofs);
 
  732                setlocale(LC_CTYPE, old);
 
struct fuse_context * fuse_get_context(void)
int(* fuse_fill_dir_t)(void *buf, const char *name, const struct stat *stbuf, off_t off, enum fuse_fill_dir_flags flags)
struct fuse_fs * fuse_fs_new(const struct fuse_operations *op, size_t op_size, void *private_data)
#define FUSE_REGISTER_MODULE(name_, factory_)
void fuse_log(enum fuse_log_level level, const char *fmt,...)
#define FUSE_OPT_KEY(templ, key)
int fuse_opt_parse(struct fuse_args *args, void *data, const struct fuse_opt opts[], fuse_opt_proc_t proc)
void(* destroy)(void *private_data)