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;
80 tmp = realloc(newpath, newpathlen + 1);
85 p = tmp + (p - newpath);
89 }
while (res == (
size_t) -1);
90 pthread_mutex_unlock(&ic->lock);
96 iconv(fromfs ? ic->fromfs : ic->tofs, NULL, NULL, NULL, NULL);
97 pthread_mutex_unlock(&ic->lock);
102 static int iconv_getattr(
const char *path,
struct stat *stbuf,
105 struct iconv *ic = iconv_get();
107 int err = iconv_convpath(ic, path, &newpath, 0);
109 err = fuse_fs_getattr(ic->next, newpath, stbuf, fi);
115 static int iconv_access(
const char *path,
int mask)
117 struct iconv *ic = iconv_get();
119 int err = iconv_convpath(ic, path, &newpath, 0);
121 err = fuse_fs_access(ic->next, newpath, mask);
127 static int iconv_readlink(
const char *path,
char *buf,
size_t size)
129 struct iconv *ic = iconv_get();
131 int err = iconv_convpath(ic, path, &newpath, 0);
133 err = fuse_fs_readlink(ic->next, newpath, buf, size);
136 err = iconv_convpath(ic, buf, &newlink, 1);
138 strncpy(buf, newlink, size - 1);
139 buf[size - 1] =
'\0';
148 static int iconv_opendir(
const char *path,
struct fuse_file_info *fi)
150 struct iconv *ic = iconv_get();
152 int err = iconv_convpath(ic, path, &newpath, 0);
154 err = fuse_fs_opendir(ic->next, newpath, fi);
160 static int iconv_dir_fill(
void *buf,
const char *name,
161 const struct stat *stbuf, off_t off,
164 struct iconv_dh *dh = buf;
167 if (iconv_convpath(dh->ic, name, &newname, 1) == 0) {
168 res = dh->prev_filler(dh->prev_buf, newname, stbuf, off, flags);
174 static int iconv_readdir(
const char *path,
void *buf,
fuse_fill_dir_t filler,
178 struct iconv *ic = iconv_get();
180 int err = iconv_convpath(ic, path, &newpath, 0);
185 dh.prev_filler = filler;
186 err = fuse_fs_readdir(ic->next, newpath, &dh, iconv_dir_fill,
193 static int iconv_releasedir(
const char *path,
struct fuse_file_info *fi)
195 struct iconv *ic = iconv_get();
197 int err = iconv_convpath(ic, path, &newpath, 0);
199 err = fuse_fs_releasedir(ic->next, newpath, fi);
205 static int iconv_mknod(
const char *path, mode_t mode, dev_t rdev)
207 struct iconv *ic = iconv_get();
209 int err = iconv_convpath(ic, path, &newpath, 0);
211 err = fuse_fs_mknod(ic->next, newpath, mode, rdev);
217 static int iconv_mkdir(
const char *path, mode_t mode)
219 struct iconv *ic = iconv_get();
221 int err = iconv_convpath(ic, path, &newpath, 0);
223 err = fuse_fs_mkdir(ic->next, newpath, mode);
229 static int iconv_unlink(
const char *path)
231 struct iconv *ic = iconv_get();
233 int err = iconv_convpath(ic, path, &newpath, 0);
235 err = fuse_fs_unlink(ic->next, newpath);
241 static int iconv_rmdir(
const char *path)
243 struct iconv *ic = iconv_get();
245 int err = iconv_convpath(ic, path, &newpath, 0);
247 err = fuse_fs_rmdir(ic->next, newpath);
253 static int iconv_symlink(
const char *from,
const char *to)
255 struct iconv *ic = iconv_get();
258 int err = iconv_convpath(ic, from, &newfrom, 0);
260 err = iconv_convpath(ic, to, &newto, 0);
262 err = fuse_fs_symlink(ic->next, newfrom, newto);
270 static int iconv_rename(
const char *from,
const char *to,
unsigned int flags)
272 struct iconv *ic = iconv_get();
275 int err = iconv_convpath(ic, from, &newfrom, 0);
277 err = iconv_convpath(ic, to, &newto, 0);
279 err = fuse_fs_rename(ic->next, newfrom, newto, flags);
287 static int iconv_link(
const char *from,
const char *to)
289 struct iconv *ic = iconv_get();
292 int err = iconv_convpath(ic, from, &newfrom, 0);
294 err = iconv_convpath(ic, to, &newto, 0);
296 err = fuse_fs_link(ic->next, newfrom, newto);
304 static int iconv_chmod(
const char *path, mode_t mode,
307 struct iconv *ic = iconv_get();
309 int err = iconv_convpath(ic, path, &newpath, 0);
311 err = fuse_fs_chmod(ic->next, newpath, mode, fi);
317 static int iconv_chown(
const char *path, uid_t uid, gid_t gid,
320 struct iconv *ic = iconv_get();
322 int err = iconv_convpath(ic, path, &newpath, 0);
324 err = fuse_fs_chown(ic->next, newpath, uid, gid, fi);
330 static int iconv_truncate(
const char *path, off_t size,
333 struct iconv *ic = iconv_get();
335 int err = iconv_convpath(ic, path, &newpath, 0);
337 err = fuse_fs_truncate(ic->next, newpath, size, fi);
343 static int iconv_utimens(
const char *path,
const struct timespec ts[2],
346 struct iconv *ic = iconv_get();
348 int err = iconv_convpath(ic, path, &newpath, 0);
350 err = fuse_fs_utimens(ic->next, newpath, ts, fi);
356 static int iconv_create(
const char *path, mode_t mode,
359 struct iconv *ic = iconv_get();
361 int err = iconv_convpath(ic, path, &newpath, 0);
363 err = fuse_fs_create(ic->next, newpath, mode, fi);
369 static int iconv_open_file(
const char *path,
struct fuse_file_info *fi)
371 struct iconv *ic = iconv_get();
373 int err = iconv_convpath(ic, path, &newpath, 0);
375 err = fuse_fs_open(ic->next, newpath, fi);
381 static int iconv_read_buf(
const char *path,
struct fuse_bufvec **bufp,
384 struct iconv *ic = iconv_get();
386 int err = iconv_convpath(ic, path, &newpath, 0);
388 err = fuse_fs_read_buf(ic->next, newpath, bufp, size, offset, fi);
394 static int iconv_write_buf(
const char *path,
struct fuse_bufvec *buf,
397 struct iconv *ic = iconv_get();
399 int err = iconv_convpath(ic, path, &newpath, 0);
401 err = fuse_fs_write_buf(ic->next, newpath, buf, offset, fi);
407 static int iconv_statfs(
const char *path,
struct statvfs *stbuf)
409 struct iconv *ic = iconv_get();
411 int err = iconv_convpath(ic, path, &newpath, 0);
413 err = fuse_fs_statfs(ic->next, newpath, stbuf);
419 static int iconv_flush(
const char *path,
struct fuse_file_info *fi)
421 struct iconv *ic = iconv_get();
423 int err = iconv_convpath(ic, path, &newpath, 0);
425 err = fuse_fs_flush(ic->next, newpath, fi);
431 static int iconv_release(
const char *path,
struct fuse_file_info *fi)
433 struct iconv *ic = iconv_get();
435 int err = iconv_convpath(ic, path, &newpath, 0);
437 err = fuse_fs_release(ic->next, newpath, fi);
443 static int iconv_fsync(
const char *path,
int isdatasync,
446 struct iconv *ic = iconv_get();
448 int err = iconv_convpath(ic, path, &newpath, 0);
450 err = fuse_fs_fsync(ic->next, newpath, isdatasync, fi);
456 static int iconv_fsyncdir(
const char *path,
int isdatasync,
459 struct iconv *ic = iconv_get();
461 int err = iconv_convpath(ic, path, &newpath, 0);
463 err = fuse_fs_fsyncdir(ic->next, newpath, isdatasync, fi);
469 static int iconv_setxattr(
const char *path,
const char *name,
470 const char *value,
size_t size,
int flags)
472 struct iconv *ic = iconv_get();
474 int err = iconv_convpath(ic, path, &newpath, 0);
476 err = fuse_fs_setxattr(ic->next, newpath, name, value, size,
483 static int iconv_getxattr(
const char *path,
const char *name,
char *value,
486 struct iconv *ic = iconv_get();
488 int err = iconv_convpath(ic, path, &newpath, 0);
490 err = fuse_fs_getxattr(ic->next, newpath, name, value, size);
496 static int iconv_listxattr(
const char *path,
char *list,
size_t size)
498 struct iconv *ic = iconv_get();
500 int err = iconv_convpath(ic, path, &newpath, 0);
502 err = fuse_fs_listxattr(ic->next, newpath, list, size);
508 static int iconv_removexattr(
const char *path,
const char *name)
510 struct iconv *ic = iconv_get();
512 int err = iconv_convpath(ic, path, &newpath, 0);
514 err = fuse_fs_removexattr(ic->next, newpath, name);
520 static int iconv_lock(
const char *path,
struct fuse_file_info *fi,
int cmd,
523 struct iconv *ic = iconv_get();
525 int err = iconv_convpath(ic, path, &newpath, 0);
527 err = fuse_fs_lock(ic->next, newpath, fi, cmd, lock);
533 static int iconv_flock(
const char *path,
struct fuse_file_info *fi,
int op)
535 struct iconv *ic = iconv_get();
537 int err = iconv_convpath(ic, path, &newpath, 0);
539 err = fuse_fs_flock(ic->next, newpath, fi, op);
545 static int iconv_bmap(
const char *path,
size_t blocksize, uint64_t *idx)
547 struct iconv *ic = iconv_get();
549 int err = iconv_convpath(ic, path, &newpath, 0);
551 err = fuse_fs_bmap(ic->next, newpath, blocksize, idx);
560 struct iconv *ic = iconv_get();
561 fuse_fs_init(ic->next, conn, cfg);
567 static void iconv_destroy(
void *data)
569 struct iconv *ic = data;
570 fuse_fs_destroy(ic->next);
571 iconv_close(ic->tofs);
572 iconv_close(ic->fromfs);
573 pthread_mutex_destroy(&ic->lock);
582 .getattr = iconv_getattr,
583 .access = iconv_access,
584 .readlink = iconv_readlink,
585 .opendir = iconv_opendir,
586 .readdir = iconv_readdir,
587 .releasedir = iconv_releasedir,
588 .mknod = iconv_mknod,
589 .mkdir = iconv_mkdir,
590 .symlink = iconv_symlink,
591 .unlink = iconv_unlink,
592 .rmdir = iconv_rmdir,
593 .rename = iconv_rename,
595 .chmod = iconv_chmod,
596 .chown = iconv_chown,
597 .truncate = iconv_truncate,
598 .utimens = iconv_utimens,
599 .create = iconv_create,
600 .open = iconv_open_file,
601 .read_buf = iconv_read_buf,
602 .write_buf = iconv_write_buf,
603 .statfs = iconv_statfs,
604 .flush = iconv_flush,
605 .release = iconv_release,
606 .fsync = iconv_fsync,
607 .fsyncdir = iconv_fsyncdir,
608 .setxattr = iconv_setxattr,
609 .getxattr = iconv_getxattr,
610 .listxattr = iconv_listxattr,
611 .removexattr = iconv_removexattr,
613 .flock = iconv_flock,
617 static const struct fuse_opt iconv_opts[] = {
620 {
"from_code=%s", offsetof(
struct iconv, from_code), 0 },
621 {
"to_code=%s", offsetof(
struct iconv, to_code), 1 },
625 static void iconv_help(
void)
627 char *old = strdup(setlocale(LC_CTYPE,
""));
628 char *charmap = strdup(nl_langinfo(CODESET));
629 setlocale(LC_CTYPE, old);
632 " -o from_code=CHARSET original encoding of file names (default: UTF-8)\n" 633 " -o to_code=CHARSET new encoding of the file names (default: %s)\n",
638 static int iconv_opt_proc(
void *data,
const char *arg,
int key,
641 (void) data; (void) arg; (void) outargs;
651 static struct fuse_fs *iconv_new(
struct fuse_args *args,
652 struct fuse_fs *next[])
660 ic = calloc(1,
sizeof(
struct iconv));
662 fprintf(stderr,
"fuse-iconv: memory allocation failed\n");
669 if (!next[0] || next[1]) {
670 fprintf(stderr,
"fuse-iconv: exactly one next filesystem required\n");
674 from = ic->from_code ? ic->from_code :
"UTF-8";
675 to = ic->to_code ? ic->to_code :
"";
678 old = strdup(setlocale(LC_CTYPE,
""));
679 ic->tofs = iconv_open(from, to);
680 if (ic->tofs == (iconv_t) -1) {
681 fprintf(stderr,
"fuse-iconv: cannot convert from %s to %s\n",
685 ic->fromfs = iconv_open(to, from);
686 if (ic->tofs == (iconv_t) -1) {
687 fprintf(stderr,
"fuse-iconv: cannot convert from %s to %s\n",
689 goto out_iconv_close_to;
692 setlocale(LC_CTYPE, old);
697 fs =
fuse_fs_new(&iconv_oper,
sizeof(iconv_oper), ic);
699 goto out_iconv_close_from;
703 out_iconv_close_from:
704 iconv_close(ic->fromfs);
706 iconv_close(ic->tofs);
712 setlocale(LC_CTYPE, old);
void(* destroy)(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)
#define FUSE_REGISTER_MODULE(name_, factory_)
struct fuse_fs * fuse_fs_new(const struct fuse_operations *op, size_t op_size, void *private_data)
struct fuse_context * fuse_get_context(void)
#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)