9 #include <fuse_config.h> 
   37 static struct iconv *iconv_get(
void)
 
   42 static 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);
 
  103 static 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);
 
  116 static 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);
 
  128 static 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';
 
  149 static 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);
 
  161 static 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);
 
  175 static 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,
 
  194 static 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);
 
  206 static 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);
 
  218 static 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);
 
  230 static 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);
 
  242 static 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);
 
  254 static 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);
 
  271 static 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);
 
  288 static 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);
 
  305 static 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);
 
  318 static 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);
 
  331 static 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);
 
  344 static 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);
 
  357 static 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);
 
  370 static 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);
 
  382 static 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);
 
  395 static 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);
 
  408 static 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);
 
  420 static 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);
 
  432 static 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);
 
  444 static 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);
 
  457 static 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);
 
  470 static 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,
 
  484 static 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);
 
  497 static 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);
 
  509 static 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);
 
  521 static 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);
 
  534 static 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);
 
  546 static 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);
 
  558 static 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);
 
  581 static 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,
 
  632 static 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 },
 
  640 static 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",
 
  658 static int iconv_opt_proc(
void *data, 
const char *arg, 
int key,
 
  661         (void) data; (void) arg; (void) outargs;
 
  671 static 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;
 
  723 out_iconv_close_from:
 
  724         iconv_close(ic->fromfs);
 
  726         iconv_close(ic->tofs);
 
  732                 setlocale(LC_CTYPE, old);
 
struct fuse_fs * fuse_fs_new(const struct fuse_operations *op, size_t op_size, void *private_data)
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_context * fuse_get_context(void)
#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)