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)