1*9e564957SAndroid Build Coastguard Worker /*
2*9e564957SAndroid Build Coastguard Worker fuse iconv module: file name charset conversion
3*9e564957SAndroid Build Coastguard Worker Copyright (C) 2007 Miklos Szeredi <[email protected]>
4*9e564957SAndroid Build Coastguard Worker
5*9e564957SAndroid Build Coastguard Worker This program can be distributed under the terms of the GNU LGPLv2.
6*9e564957SAndroid Build Coastguard Worker See the file COPYING.LIB
7*9e564957SAndroid Build Coastguard Worker */
8*9e564957SAndroid Build Coastguard Worker
9*9e564957SAndroid Build Coastguard Worker #include <fuse_config.h>
10*9e564957SAndroid Build Coastguard Worker
11*9e564957SAndroid Build Coastguard Worker #include <fuse.h>
12*9e564957SAndroid Build Coastguard Worker #include <stdio.h>
13*9e564957SAndroid Build Coastguard Worker #include <stdlib.h>
14*9e564957SAndroid Build Coastguard Worker #include <stddef.h>
15*9e564957SAndroid Build Coastguard Worker #include <string.h>
16*9e564957SAndroid Build Coastguard Worker #include <errno.h>
17*9e564957SAndroid Build Coastguard Worker #include <iconv.h>
18*9e564957SAndroid Build Coastguard Worker #include <pthread.h>
19*9e564957SAndroid Build Coastguard Worker #include <locale.h>
20*9e564957SAndroid Build Coastguard Worker #include <langinfo.h>
21*9e564957SAndroid Build Coastguard Worker
22*9e564957SAndroid Build Coastguard Worker struct iconv {
23*9e564957SAndroid Build Coastguard Worker struct fuse_fs *next;
24*9e564957SAndroid Build Coastguard Worker pthread_mutex_t lock;
25*9e564957SAndroid Build Coastguard Worker char *from_code;
26*9e564957SAndroid Build Coastguard Worker char *to_code;
27*9e564957SAndroid Build Coastguard Worker iconv_t tofs;
28*9e564957SAndroid Build Coastguard Worker iconv_t fromfs;
29*9e564957SAndroid Build Coastguard Worker };
30*9e564957SAndroid Build Coastguard Worker
31*9e564957SAndroid Build Coastguard Worker struct iconv_dh {
32*9e564957SAndroid Build Coastguard Worker struct iconv *ic;
33*9e564957SAndroid Build Coastguard Worker void *prev_buf;
34*9e564957SAndroid Build Coastguard Worker fuse_fill_dir_t prev_filler;
35*9e564957SAndroid Build Coastguard Worker };
36*9e564957SAndroid Build Coastguard Worker
iconv_get(void)37*9e564957SAndroid Build Coastguard Worker static struct iconv *iconv_get(void)
38*9e564957SAndroid Build Coastguard Worker {
39*9e564957SAndroid Build Coastguard Worker return fuse_get_context()->private_data;
40*9e564957SAndroid Build Coastguard Worker }
41*9e564957SAndroid Build Coastguard Worker
iconv_convpath(struct iconv * ic,const char * path,char ** newpathp,int fromfs)42*9e564957SAndroid Build Coastguard Worker static int iconv_convpath(struct iconv *ic, const char *path, char **newpathp,
43*9e564957SAndroid Build Coastguard Worker int fromfs)
44*9e564957SAndroid Build Coastguard Worker {
45*9e564957SAndroid Build Coastguard Worker size_t pathlen;
46*9e564957SAndroid Build Coastguard Worker size_t newpathlen;
47*9e564957SAndroid Build Coastguard Worker char *newpath;
48*9e564957SAndroid Build Coastguard Worker size_t plen;
49*9e564957SAndroid Build Coastguard Worker char *p;
50*9e564957SAndroid Build Coastguard Worker size_t res;
51*9e564957SAndroid Build Coastguard Worker int err;
52*9e564957SAndroid Build Coastguard Worker
53*9e564957SAndroid Build Coastguard Worker if (path == NULL) {
54*9e564957SAndroid Build Coastguard Worker *newpathp = NULL;
55*9e564957SAndroid Build Coastguard Worker return 0;
56*9e564957SAndroid Build Coastguard Worker }
57*9e564957SAndroid Build Coastguard Worker
58*9e564957SAndroid Build Coastguard Worker pathlen = strlen(path);
59*9e564957SAndroid Build Coastguard Worker newpathlen = pathlen * 4;
60*9e564957SAndroid Build Coastguard Worker newpath = malloc(newpathlen + 1);
61*9e564957SAndroid Build Coastguard Worker if (!newpath)
62*9e564957SAndroid Build Coastguard Worker return -ENOMEM;
63*9e564957SAndroid Build Coastguard Worker
64*9e564957SAndroid Build Coastguard Worker plen = newpathlen;
65*9e564957SAndroid Build Coastguard Worker p = newpath;
66*9e564957SAndroid Build Coastguard Worker pthread_mutex_lock(&ic->lock);
67*9e564957SAndroid Build Coastguard Worker do {
68*9e564957SAndroid Build Coastguard Worker res = iconv(fromfs ? ic->fromfs : ic->tofs, (char **) &path,
69*9e564957SAndroid Build Coastguard Worker &pathlen, &p, &plen);
70*9e564957SAndroid Build Coastguard Worker if (res == (size_t) -1) {
71*9e564957SAndroid Build Coastguard Worker char *tmp;
72*9e564957SAndroid Build Coastguard Worker size_t inc;
73*9e564957SAndroid Build Coastguard Worker
74*9e564957SAndroid Build Coastguard Worker err = -EILSEQ;
75*9e564957SAndroid Build Coastguard Worker if (errno != E2BIG)
76*9e564957SAndroid Build Coastguard Worker goto err;
77*9e564957SAndroid Build Coastguard Worker
78*9e564957SAndroid Build Coastguard Worker inc = (pathlen + 1) * 4;
79*9e564957SAndroid Build Coastguard Worker newpathlen += inc;
80*9e564957SAndroid Build Coastguard Worker int dp = p - newpath;
81*9e564957SAndroid Build Coastguard Worker tmp = realloc(newpath, newpathlen + 1);
82*9e564957SAndroid Build Coastguard Worker err = -ENOMEM;
83*9e564957SAndroid Build Coastguard Worker if (!tmp)
84*9e564957SAndroid Build Coastguard Worker goto err;
85*9e564957SAndroid Build Coastguard Worker
86*9e564957SAndroid Build Coastguard Worker p = tmp + dp;
87*9e564957SAndroid Build Coastguard Worker plen += inc;
88*9e564957SAndroid Build Coastguard Worker newpath = tmp;
89*9e564957SAndroid Build Coastguard Worker }
90*9e564957SAndroid Build Coastguard Worker } while (res == (size_t) -1);
91*9e564957SAndroid Build Coastguard Worker pthread_mutex_unlock(&ic->lock);
92*9e564957SAndroid Build Coastguard Worker *p = '\0';
93*9e564957SAndroid Build Coastguard Worker *newpathp = newpath;
94*9e564957SAndroid Build Coastguard Worker return 0;
95*9e564957SAndroid Build Coastguard Worker
96*9e564957SAndroid Build Coastguard Worker err:
97*9e564957SAndroid Build Coastguard Worker iconv(fromfs ? ic->fromfs : ic->tofs, NULL, NULL, NULL, NULL);
98*9e564957SAndroid Build Coastguard Worker pthread_mutex_unlock(&ic->lock);
99*9e564957SAndroid Build Coastguard Worker free(newpath);
100*9e564957SAndroid Build Coastguard Worker return err;
101*9e564957SAndroid Build Coastguard Worker }
102*9e564957SAndroid Build Coastguard Worker
iconv_getattr(const char * path,struct stat * stbuf,struct fuse_file_info * fi)103*9e564957SAndroid Build Coastguard Worker static int iconv_getattr(const char *path, struct stat *stbuf,
104*9e564957SAndroid Build Coastguard Worker struct fuse_file_info *fi)
105*9e564957SAndroid Build Coastguard Worker {
106*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
107*9e564957SAndroid Build Coastguard Worker char *newpath;
108*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
109*9e564957SAndroid Build Coastguard Worker if (!err) {
110*9e564957SAndroid Build Coastguard Worker err = fuse_fs_getattr(ic->next, newpath, stbuf, fi);
111*9e564957SAndroid Build Coastguard Worker free(newpath);
112*9e564957SAndroid Build Coastguard Worker }
113*9e564957SAndroid Build Coastguard Worker return err;
114*9e564957SAndroid Build Coastguard Worker }
115*9e564957SAndroid Build Coastguard Worker
iconv_access(const char * path,int mask)116*9e564957SAndroid Build Coastguard Worker static int iconv_access(const char *path, int mask)
117*9e564957SAndroid Build Coastguard Worker {
118*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
119*9e564957SAndroid Build Coastguard Worker char *newpath;
120*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
121*9e564957SAndroid Build Coastguard Worker if (!err) {
122*9e564957SAndroid Build Coastguard Worker err = fuse_fs_access(ic->next, newpath, mask);
123*9e564957SAndroid Build Coastguard Worker free(newpath);
124*9e564957SAndroid Build Coastguard Worker }
125*9e564957SAndroid Build Coastguard Worker return err;
126*9e564957SAndroid Build Coastguard Worker }
127*9e564957SAndroid Build Coastguard Worker
iconv_readlink(const char * path,char * buf,size_t size)128*9e564957SAndroid Build Coastguard Worker static int iconv_readlink(const char *path, char *buf, size_t size)
129*9e564957SAndroid Build Coastguard Worker {
130*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
131*9e564957SAndroid Build Coastguard Worker char *newpath;
132*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
133*9e564957SAndroid Build Coastguard Worker if (!err) {
134*9e564957SAndroid Build Coastguard Worker err = fuse_fs_readlink(ic->next, newpath, buf, size);
135*9e564957SAndroid Build Coastguard Worker if (!err) {
136*9e564957SAndroid Build Coastguard Worker char *newlink;
137*9e564957SAndroid Build Coastguard Worker err = iconv_convpath(ic, buf, &newlink, 1);
138*9e564957SAndroid Build Coastguard Worker if (!err) {
139*9e564957SAndroid Build Coastguard Worker strncpy(buf, newlink, size - 1);
140*9e564957SAndroid Build Coastguard Worker buf[size - 1] = '\0';
141*9e564957SAndroid Build Coastguard Worker free(newlink);
142*9e564957SAndroid Build Coastguard Worker }
143*9e564957SAndroid Build Coastguard Worker }
144*9e564957SAndroid Build Coastguard Worker free(newpath);
145*9e564957SAndroid Build Coastguard Worker }
146*9e564957SAndroid Build Coastguard Worker return err;
147*9e564957SAndroid Build Coastguard Worker }
148*9e564957SAndroid Build Coastguard Worker
iconv_opendir(const char * path,struct fuse_file_info * fi)149*9e564957SAndroid Build Coastguard Worker static int iconv_opendir(const char *path, struct fuse_file_info *fi)
150*9e564957SAndroid Build Coastguard Worker {
151*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
152*9e564957SAndroid Build Coastguard Worker char *newpath;
153*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
154*9e564957SAndroid Build Coastguard Worker if (!err) {
155*9e564957SAndroid Build Coastguard Worker err = fuse_fs_opendir(ic->next, newpath, fi);
156*9e564957SAndroid Build Coastguard Worker free(newpath);
157*9e564957SAndroid Build Coastguard Worker }
158*9e564957SAndroid Build Coastguard Worker return err;
159*9e564957SAndroid Build Coastguard Worker }
160*9e564957SAndroid Build Coastguard Worker
iconv_dir_fill(void * buf,const char * name,const struct stat * stbuf,off_t off,enum fuse_fill_dir_flags flags)161*9e564957SAndroid Build Coastguard Worker static int iconv_dir_fill(void *buf, const char *name,
162*9e564957SAndroid Build Coastguard Worker const struct stat *stbuf, off_t off,
163*9e564957SAndroid Build Coastguard Worker enum fuse_fill_dir_flags flags)
164*9e564957SAndroid Build Coastguard Worker {
165*9e564957SAndroid Build Coastguard Worker struct iconv_dh *dh = buf;
166*9e564957SAndroid Build Coastguard Worker char *newname;
167*9e564957SAndroid Build Coastguard Worker int res = 0;
168*9e564957SAndroid Build Coastguard Worker if (iconv_convpath(dh->ic, name, &newname, 1) == 0) {
169*9e564957SAndroid Build Coastguard Worker res = dh->prev_filler(dh->prev_buf, newname, stbuf, off, flags);
170*9e564957SAndroid Build Coastguard Worker free(newname);
171*9e564957SAndroid Build Coastguard Worker }
172*9e564957SAndroid Build Coastguard Worker return res;
173*9e564957SAndroid Build Coastguard Worker }
174*9e564957SAndroid Build Coastguard Worker
iconv_readdir(const char * path,void * buf,fuse_fill_dir_t filler,off_t offset,struct fuse_file_info * fi,enum fuse_readdir_flags flags)175*9e564957SAndroid Build Coastguard Worker static int iconv_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
176*9e564957SAndroid Build Coastguard Worker off_t offset, struct fuse_file_info *fi,
177*9e564957SAndroid Build Coastguard Worker enum fuse_readdir_flags flags)
178*9e564957SAndroid Build Coastguard Worker {
179*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
180*9e564957SAndroid Build Coastguard Worker char *newpath;
181*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
182*9e564957SAndroid Build Coastguard Worker if (!err) {
183*9e564957SAndroid Build Coastguard Worker struct iconv_dh dh;
184*9e564957SAndroid Build Coastguard Worker dh.ic = ic;
185*9e564957SAndroid Build Coastguard Worker dh.prev_buf = buf;
186*9e564957SAndroid Build Coastguard Worker dh.prev_filler = filler;
187*9e564957SAndroid Build Coastguard Worker err = fuse_fs_readdir(ic->next, newpath, &dh, iconv_dir_fill,
188*9e564957SAndroid Build Coastguard Worker offset, fi, flags);
189*9e564957SAndroid Build Coastguard Worker free(newpath);
190*9e564957SAndroid Build Coastguard Worker }
191*9e564957SAndroid Build Coastguard Worker return err;
192*9e564957SAndroid Build Coastguard Worker }
193*9e564957SAndroid Build Coastguard Worker
iconv_releasedir(const char * path,struct fuse_file_info * fi)194*9e564957SAndroid Build Coastguard Worker static int iconv_releasedir(const char *path, struct fuse_file_info *fi)
195*9e564957SAndroid Build Coastguard Worker {
196*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
197*9e564957SAndroid Build Coastguard Worker char *newpath;
198*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
199*9e564957SAndroid Build Coastguard Worker if (!err) {
200*9e564957SAndroid Build Coastguard Worker err = fuse_fs_releasedir(ic->next, newpath, fi);
201*9e564957SAndroid Build Coastguard Worker free(newpath);
202*9e564957SAndroid Build Coastguard Worker }
203*9e564957SAndroid Build Coastguard Worker return err;
204*9e564957SAndroid Build Coastguard Worker }
205*9e564957SAndroid Build Coastguard Worker
iconv_mknod(const char * path,mode_t mode,dev_t rdev)206*9e564957SAndroid Build Coastguard Worker static int iconv_mknod(const char *path, mode_t mode, dev_t rdev)
207*9e564957SAndroid Build Coastguard Worker {
208*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
209*9e564957SAndroid Build Coastguard Worker char *newpath;
210*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
211*9e564957SAndroid Build Coastguard Worker if (!err) {
212*9e564957SAndroid Build Coastguard Worker err = fuse_fs_mknod(ic->next, newpath, mode, rdev);
213*9e564957SAndroid Build Coastguard Worker free(newpath);
214*9e564957SAndroid Build Coastguard Worker }
215*9e564957SAndroid Build Coastguard Worker return err;
216*9e564957SAndroid Build Coastguard Worker }
217*9e564957SAndroid Build Coastguard Worker
iconv_mkdir(const char * path,mode_t mode)218*9e564957SAndroid Build Coastguard Worker static int iconv_mkdir(const char *path, mode_t mode)
219*9e564957SAndroid Build Coastguard Worker {
220*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
221*9e564957SAndroid Build Coastguard Worker char *newpath;
222*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
223*9e564957SAndroid Build Coastguard Worker if (!err) {
224*9e564957SAndroid Build Coastguard Worker err = fuse_fs_mkdir(ic->next, newpath, mode);
225*9e564957SAndroid Build Coastguard Worker free(newpath);
226*9e564957SAndroid Build Coastguard Worker }
227*9e564957SAndroid Build Coastguard Worker return err;
228*9e564957SAndroid Build Coastguard Worker }
229*9e564957SAndroid Build Coastguard Worker
iconv_unlink(const char * path)230*9e564957SAndroid Build Coastguard Worker static int iconv_unlink(const char *path)
231*9e564957SAndroid Build Coastguard Worker {
232*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
233*9e564957SAndroid Build Coastguard Worker char *newpath;
234*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
235*9e564957SAndroid Build Coastguard Worker if (!err) {
236*9e564957SAndroid Build Coastguard Worker err = fuse_fs_unlink(ic->next, newpath);
237*9e564957SAndroid Build Coastguard Worker free(newpath);
238*9e564957SAndroid Build Coastguard Worker }
239*9e564957SAndroid Build Coastguard Worker return err;
240*9e564957SAndroid Build Coastguard Worker }
241*9e564957SAndroid Build Coastguard Worker
iconv_rmdir(const char * path)242*9e564957SAndroid Build Coastguard Worker static int iconv_rmdir(const char *path)
243*9e564957SAndroid Build Coastguard Worker {
244*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
245*9e564957SAndroid Build Coastguard Worker char *newpath;
246*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
247*9e564957SAndroid Build Coastguard Worker if (!err) {
248*9e564957SAndroid Build Coastguard Worker err = fuse_fs_rmdir(ic->next, newpath);
249*9e564957SAndroid Build Coastguard Worker free(newpath);
250*9e564957SAndroid Build Coastguard Worker }
251*9e564957SAndroid Build Coastguard Worker return err;
252*9e564957SAndroid Build Coastguard Worker }
253*9e564957SAndroid Build Coastguard Worker
iconv_symlink(const char * from,const char * to)254*9e564957SAndroid Build Coastguard Worker static int iconv_symlink(const char *from, const char *to)
255*9e564957SAndroid Build Coastguard Worker {
256*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
257*9e564957SAndroid Build Coastguard Worker char *newfrom;
258*9e564957SAndroid Build Coastguard Worker char *newto;
259*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, from, &newfrom, 0);
260*9e564957SAndroid Build Coastguard Worker if (!err) {
261*9e564957SAndroid Build Coastguard Worker err = iconv_convpath(ic, to, &newto, 0);
262*9e564957SAndroid Build Coastguard Worker if (!err) {
263*9e564957SAndroid Build Coastguard Worker err = fuse_fs_symlink(ic->next, newfrom, newto);
264*9e564957SAndroid Build Coastguard Worker free(newto);
265*9e564957SAndroid Build Coastguard Worker }
266*9e564957SAndroid Build Coastguard Worker free(newfrom);
267*9e564957SAndroid Build Coastguard Worker }
268*9e564957SAndroid Build Coastguard Worker return err;
269*9e564957SAndroid Build Coastguard Worker }
270*9e564957SAndroid Build Coastguard Worker
iconv_rename(const char * from,const char * to,unsigned int flags)271*9e564957SAndroid Build Coastguard Worker static int iconv_rename(const char *from, const char *to, unsigned int flags)
272*9e564957SAndroid Build Coastguard Worker {
273*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
274*9e564957SAndroid Build Coastguard Worker char *newfrom;
275*9e564957SAndroid Build Coastguard Worker char *newto;
276*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, from, &newfrom, 0);
277*9e564957SAndroid Build Coastguard Worker if (!err) {
278*9e564957SAndroid Build Coastguard Worker err = iconv_convpath(ic, to, &newto, 0);
279*9e564957SAndroid Build Coastguard Worker if (!err) {
280*9e564957SAndroid Build Coastguard Worker err = fuse_fs_rename(ic->next, newfrom, newto, flags);
281*9e564957SAndroid Build Coastguard Worker free(newto);
282*9e564957SAndroid Build Coastguard Worker }
283*9e564957SAndroid Build Coastguard Worker free(newfrom);
284*9e564957SAndroid Build Coastguard Worker }
285*9e564957SAndroid Build Coastguard Worker return err;
286*9e564957SAndroid Build Coastguard Worker }
287*9e564957SAndroid Build Coastguard Worker
iconv_link(const char * from,const char * to)288*9e564957SAndroid Build Coastguard Worker static int iconv_link(const char *from, const char *to)
289*9e564957SAndroid Build Coastguard Worker {
290*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
291*9e564957SAndroid Build Coastguard Worker char *newfrom;
292*9e564957SAndroid Build Coastguard Worker char *newto;
293*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, from, &newfrom, 0);
294*9e564957SAndroid Build Coastguard Worker if (!err) {
295*9e564957SAndroid Build Coastguard Worker err = iconv_convpath(ic, to, &newto, 0);
296*9e564957SAndroid Build Coastguard Worker if (!err) {
297*9e564957SAndroid Build Coastguard Worker err = fuse_fs_link(ic->next, newfrom, newto);
298*9e564957SAndroid Build Coastguard Worker free(newto);
299*9e564957SAndroid Build Coastguard Worker }
300*9e564957SAndroid Build Coastguard Worker free(newfrom);
301*9e564957SAndroid Build Coastguard Worker }
302*9e564957SAndroid Build Coastguard Worker return err;
303*9e564957SAndroid Build Coastguard Worker }
304*9e564957SAndroid Build Coastguard Worker
iconv_chmod(const char * path,mode_t mode,struct fuse_file_info * fi)305*9e564957SAndroid Build Coastguard Worker static int iconv_chmod(const char *path, mode_t mode,
306*9e564957SAndroid Build Coastguard Worker struct fuse_file_info *fi)
307*9e564957SAndroid Build Coastguard Worker {
308*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
309*9e564957SAndroid Build Coastguard Worker char *newpath;
310*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
311*9e564957SAndroid Build Coastguard Worker if (!err) {
312*9e564957SAndroid Build Coastguard Worker err = fuse_fs_chmod(ic->next, newpath, mode, fi);
313*9e564957SAndroid Build Coastguard Worker free(newpath);
314*9e564957SAndroid Build Coastguard Worker }
315*9e564957SAndroid Build Coastguard Worker return err;
316*9e564957SAndroid Build Coastguard Worker }
317*9e564957SAndroid Build Coastguard Worker
iconv_chown(const char * path,uid_t uid,gid_t gid,struct fuse_file_info * fi)318*9e564957SAndroid Build Coastguard Worker static int iconv_chown(const char *path, uid_t uid, gid_t gid,
319*9e564957SAndroid Build Coastguard Worker struct fuse_file_info *fi)
320*9e564957SAndroid Build Coastguard Worker {
321*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
322*9e564957SAndroid Build Coastguard Worker char *newpath;
323*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
324*9e564957SAndroid Build Coastguard Worker if (!err) {
325*9e564957SAndroid Build Coastguard Worker err = fuse_fs_chown(ic->next, newpath, uid, gid, fi);
326*9e564957SAndroid Build Coastguard Worker free(newpath);
327*9e564957SAndroid Build Coastguard Worker }
328*9e564957SAndroid Build Coastguard Worker return err;
329*9e564957SAndroid Build Coastguard Worker }
330*9e564957SAndroid Build Coastguard Worker
iconv_truncate(const char * path,off_t size,struct fuse_file_info * fi)331*9e564957SAndroid Build Coastguard Worker static int iconv_truncate(const char *path, off_t size,
332*9e564957SAndroid Build Coastguard Worker struct fuse_file_info *fi)
333*9e564957SAndroid Build Coastguard Worker {
334*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
335*9e564957SAndroid Build Coastguard Worker char *newpath;
336*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
337*9e564957SAndroid Build Coastguard Worker if (!err) {
338*9e564957SAndroid Build Coastguard Worker err = fuse_fs_truncate(ic->next, newpath, size, fi);
339*9e564957SAndroid Build Coastguard Worker free(newpath);
340*9e564957SAndroid Build Coastguard Worker }
341*9e564957SAndroid Build Coastguard Worker return err;
342*9e564957SAndroid Build Coastguard Worker }
343*9e564957SAndroid Build Coastguard Worker
iconv_utimens(const char * path,const struct timespec ts[2],struct fuse_file_info * fi)344*9e564957SAndroid Build Coastguard Worker static int iconv_utimens(const char *path, const struct timespec ts[2],
345*9e564957SAndroid Build Coastguard Worker struct fuse_file_info *fi)
346*9e564957SAndroid Build Coastguard Worker {
347*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
348*9e564957SAndroid Build Coastguard Worker char *newpath;
349*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
350*9e564957SAndroid Build Coastguard Worker if (!err) {
351*9e564957SAndroid Build Coastguard Worker err = fuse_fs_utimens(ic->next, newpath, ts, fi);
352*9e564957SAndroid Build Coastguard Worker free(newpath);
353*9e564957SAndroid Build Coastguard Worker }
354*9e564957SAndroid Build Coastguard Worker return err;
355*9e564957SAndroid Build Coastguard Worker }
356*9e564957SAndroid Build Coastguard Worker
iconv_create(const char * path,mode_t mode,struct fuse_file_info * fi)357*9e564957SAndroid Build Coastguard Worker static int iconv_create(const char *path, mode_t mode,
358*9e564957SAndroid Build Coastguard Worker struct fuse_file_info *fi)
359*9e564957SAndroid Build Coastguard Worker {
360*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
361*9e564957SAndroid Build Coastguard Worker char *newpath;
362*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
363*9e564957SAndroid Build Coastguard Worker if (!err) {
364*9e564957SAndroid Build Coastguard Worker err = fuse_fs_create(ic->next, newpath, mode, fi);
365*9e564957SAndroid Build Coastguard Worker free(newpath);
366*9e564957SAndroid Build Coastguard Worker }
367*9e564957SAndroid Build Coastguard Worker return err;
368*9e564957SAndroid Build Coastguard Worker }
369*9e564957SAndroid Build Coastguard Worker
iconv_open_file(const char * path,struct fuse_file_info * fi)370*9e564957SAndroid Build Coastguard Worker static int iconv_open_file(const char *path, struct fuse_file_info *fi)
371*9e564957SAndroid Build Coastguard Worker {
372*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
373*9e564957SAndroid Build Coastguard Worker char *newpath;
374*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
375*9e564957SAndroid Build Coastguard Worker if (!err) {
376*9e564957SAndroid Build Coastguard Worker err = fuse_fs_open(ic->next, newpath, fi);
377*9e564957SAndroid Build Coastguard Worker free(newpath);
378*9e564957SAndroid Build Coastguard Worker }
379*9e564957SAndroid Build Coastguard Worker return err;
380*9e564957SAndroid Build Coastguard Worker }
381*9e564957SAndroid Build Coastguard Worker
iconv_read_buf(const char * path,struct fuse_bufvec ** bufp,size_t size,off_t offset,struct fuse_file_info * fi)382*9e564957SAndroid Build Coastguard Worker static int iconv_read_buf(const char *path, struct fuse_bufvec **bufp,
383*9e564957SAndroid Build Coastguard Worker size_t size, off_t offset, struct fuse_file_info *fi)
384*9e564957SAndroid Build Coastguard Worker {
385*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
386*9e564957SAndroid Build Coastguard Worker char *newpath;
387*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
388*9e564957SAndroid Build Coastguard Worker if (!err) {
389*9e564957SAndroid Build Coastguard Worker err = fuse_fs_read_buf(ic->next, newpath, bufp, size, offset, fi);
390*9e564957SAndroid Build Coastguard Worker free(newpath);
391*9e564957SAndroid Build Coastguard Worker }
392*9e564957SAndroid Build Coastguard Worker return err;
393*9e564957SAndroid Build Coastguard Worker }
394*9e564957SAndroid Build Coastguard Worker
iconv_write_buf(const char * path,struct fuse_bufvec * buf,off_t offset,struct fuse_file_info * fi)395*9e564957SAndroid Build Coastguard Worker static int iconv_write_buf(const char *path, struct fuse_bufvec *buf,
396*9e564957SAndroid Build Coastguard Worker off_t offset, struct fuse_file_info *fi)
397*9e564957SAndroid Build Coastguard Worker {
398*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
399*9e564957SAndroid Build Coastguard Worker char *newpath;
400*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
401*9e564957SAndroid Build Coastguard Worker if (!err) {
402*9e564957SAndroid Build Coastguard Worker err = fuse_fs_write_buf(ic->next, newpath, buf, offset, fi);
403*9e564957SAndroid Build Coastguard Worker free(newpath);
404*9e564957SAndroid Build Coastguard Worker }
405*9e564957SAndroid Build Coastguard Worker return err;
406*9e564957SAndroid Build Coastguard Worker }
407*9e564957SAndroid Build Coastguard Worker
iconv_statfs(const char * path,struct statvfs * stbuf)408*9e564957SAndroid Build Coastguard Worker static int iconv_statfs(const char *path, struct statvfs *stbuf)
409*9e564957SAndroid Build Coastguard Worker {
410*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
411*9e564957SAndroid Build Coastguard Worker char *newpath;
412*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
413*9e564957SAndroid Build Coastguard Worker if (!err) {
414*9e564957SAndroid Build Coastguard Worker err = fuse_fs_statfs(ic->next, newpath, stbuf);
415*9e564957SAndroid Build Coastguard Worker free(newpath);
416*9e564957SAndroid Build Coastguard Worker }
417*9e564957SAndroid Build Coastguard Worker return err;
418*9e564957SAndroid Build Coastguard Worker }
419*9e564957SAndroid Build Coastguard Worker
iconv_flush(const char * path,struct fuse_file_info * fi)420*9e564957SAndroid Build Coastguard Worker static int iconv_flush(const char *path, struct fuse_file_info *fi)
421*9e564957SAndroid Build Coastguard Worker {
422*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
423*9e564957SAndroid Build Coastguard Worker char *newpath;
424*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
425*9e564957SAndroid Build Coastguard Worker if (!err) {
426*9e564957SAndroid Build Coastguard Worker err = fuse_fs_flush(ic->next, newpath, fi);
427*9e564957SAndroid Build Coastguard Worker free(newpath);
428*9e564957SAndroid Build Coastguard Worker }
429*9e564957SAndroid Build Coastguard Worker return err;
430*9e564957SAndroid Build Coastguard Worker }
431*9e564957SAndroid Build Coastguard Worker
iconv_release(const char * path,struct fuse_file_info * fi)432*9e564957SAndroid Build Coastguard Worker static int iconv_release(const char *path, struct fuse_file_info *fi)
433*9e564957SAndroid Build Coastguard Worker {
434*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
435*9e564957SAndroid Build Coastguard Worker char *newpath;
436*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
437*9e564957SAndroid Build Coastguard Worker if (!err) {
438*9e564957SAndroid Build Coastguard Worker err = fuse_fs_release(ic->next, newpath, fi);
439*9e564957SAndroid Build Coastguard Worker free(newpath);
440*9e564957SAndroid Build Coastguard Worker }
441*9e564957SAndroid Build Coastguard Worker return err;
442*9e564957SAndroid Build Coastguard Worker }
443*9e564957SAndroid Build Coastguard Worker
iconv_fsync(const char * path,int isdatasync,struct fuse_file_info * fi)444*9e564957SAndroid Build Coastguard Worker static int iconv_fsync(const char *path, int isdatasync,
445*9e564957SAndroid Build Coastguard Worker struct fuse_file_info *fi)
446*9e564957SAndroid Build Coastguard Worker {
447*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
448*9e564957SAndroid Build Coastguard Worker char *newpath;
449*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
450*9e564957SAndroid Build Coastguard Worker if (!err) {
451*9e564957SAndroid Build Coastguard Worker err = fuse_fs_fsync(ic->next, newpath, isdatasync, fi);
452*9e564957SAndroid Build Coastguard Worker free(newpath);
453*9e564957SAndroid Build Coastguard Worker }
454*9e564957SAndroid Build Coastguard Worker return err;
455*9e564957SAndroid Build Coastguard Worker }
456*9e564957SAndroid Build Coastguard Worker
iconv_fsyncdir(const char * path,int isdatasync,struct fuse_file_info * fi)457*9e564957SAndroid Build Coastguard Worker static int iconv_fsyncdir(const char *path, int isdatasync,
458*9e564957SAndroid Build Coastguard Worker struct fuse_file_info *fi)
459*9e564957SAndroid Build Coastguard Worker {
460*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
461*9e564957SAndroid Build Coastguard Worker char *newpath;
462*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
463*9e564957SAndroid Build Coastguard Worker if (!err) {
464*9e564957SAndroid Build Coastguard Worker err = fuse_fs_fsyncdir(ic->next, newpath, isdatasync, fi);
465*9e564957SAndroid Build Coastguard Worker free(newpath);
466*9e564957SAndroid Build Coastguard Worker }
467*9e564957SAndroid Build Coastguard Worker return err;
468*9e564957SAndroid Build Coastguard Worker }
469*9e564957SAndroid Build Coastguard Worker
iconv_setxattr(const char * path,const char * name,const char * value,size_t size,int flags)470*9e564957SAndroid Build Coastguard Worker static int iconv_setxattr(const char *path, const char *name,
471*9e564957SAndroid Build Coastguard Worker const char *value, size_t size, int flags)
472*9e564957SAndroid Build Coastguard Worker {
473*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
474*9e564957SAndroid Build Coastguard Worker char *newpath;
475*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
476*9e564957SAndroid Build Coastguard Worker if (!err) {
477*9e564957SAndroid Build Coastguard Worker err = fuse_fs_setxattr(ic->next, newpath, name, value, size,
478*9e564957SAndroid Build Coastguard Worker flags);
479*9e564957SAndroid Build Coastguard Worker free(newpath);
480*9e564957SAndroid Build Coastguard Worker }
481*9e564957SAndroid Build Coastguard Worker return err;
482*9e564957SAndroid Build Coastguard Worker }
483*9e564957SAndroid Build Coastguard Worker
iconv_getxattr(const char * path,const char * name,char * value,size_t size)484*9e564957SAndroid Build Coastguard Worker static int iconv_getxattr(const char *path, const char *name, char *value,
485*9e564957SAndroid Build Coastguard Worker size_t size)
486*9e564957SAndroid Build Coastguard Worker {
487*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
488*9e564957SAndroid Build Coastguard Worker char *newpath;
489*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
490*9e564957SAndroid Build Coastguard Worker if (!err) {
491*9e564957SAndroid Build Coastguard Worker err = fuse_fs_getxattr(ic->next, newpath, name, value, size);
492*9e564957SAndroid Build Coastguard Worker free(newpath);
493*9e564957SAndroid Build Coastguard Worker }
494*9e564957SAndroid Build Coastguard Worker return err;
495*9e564957SAndroid Build Coastguard Worker }
496*9e564957SAndroid Build Coastguard Worker
iconv_listxattr(const char * path,char * list,size_t size)497*9e564957SAndroid Build Coastguard Worker static int iconv_listxattr(const char *path, char *list, size_t size)
498*9e564957SAndroid Build Coastguard Worker {
499*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
500*9e564957SAndroid Build Coastguard Worker char *newpath;
501*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
502*9e564957SAndroid Build Coastguard Worker if (!err) {
503*9e564957SAndroid Build Coastguard Worker err = fuse_fs_listxattr(ic->next, newpath, list, size);
504*9e564957SAndroid Build Coastguard Worker free(newpath);
505*9e564957SAndroid Build Coastguard Worker }
506*9e564957SAndroid Build Coastguard Worker return err;
507*9e564957SAndroid Build Coastguard Worker }
508*9e564957SAndroid Build Coastguard Worker
iconv_removexattr(const char * path,const char * name)509*9e564957SAndroid Build Coastguard Worker static int iconv_removexattr(const char *path, const char *name)
510*9e564957SAndroid Build Coastguard Worker {
511*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
512*9e564957SAndroid Build Coastguard Worker char *newpath;
513*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
514*9e564957SAndroid Build Coastguard Worker if (!err) {
515*9e564957SAndroid Build Coastguard Worker err = fuse_fs_removexattr(ic->next, newpath, name);
516*9e564957SAndroid Build Coastguard Worker free(newpath);
517*9e564957SAndroid Build Coastguard Worker }
518*9e564957SAndroid Build Coastguard Worker return err;
519*9e564957SAndroid Build Coastguard Worker }
520*9e564957SAndroid Build Coastguard Worker
iconv_lock(const char * path,struct fuse_file_info * fi,int cmd,struct flock * lock)521*9e564957SAndroid Build Coastguard Worker static int iconv_lock(const char *path, struct fuse_file_info *fi, int cmd,
522*9e564957SAndroid Build Coastguard Worker struct flock *lock)
523*9e564957SAndroid Build Coastguard Worker {
524*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
525*9e564957SAndroid Build Coastguard Worker char *newpath;
526*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
527*9e564957SAndroid Build Coastguard Worker if (!err) {
528*9e564957SAndroid Build Coastguard Worker err = fuse_fs_lock(ic->next, newpath, fi, cmd, lock);
529*9e564957SAndroid Build Coastguard Worker free(newpath);
530*9e564957SAndroid Build Coastguard Worker }
531*9e564957SAndroid Build Coastguard Worker return err;
532*9e564957SAndroid Build Coastguard Worker }
533*9e564957SAndroid Build Coastguard Worker
iconv_flock(const char * path,struct fuse_file_info * fi,int op)534*9e564957SAndroid Build Coastguard Worker static int iconv_flock(const char *path, struct fuse_file_info *fi, int op)
535*9e564957SAndroid Build Coastguard Worker {
536*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
537*9e564957SAndroid Build Coastguard Worker char *newpath;
538*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
539*9e564957SAndroid Build Coastguard Worker if (!err) {
540*9e564957SAndroid Build Coastguard Worker err = fuse_fs_flock(ic->next, newpath, fi, op);
541*9e564957SAndroid Build Coastguard Worker free(newpath);
542*9e564957SAndroid Build Coastguard Worker }
543*9e564957SAndroid Build Coastguard Worker return err;
544*9e564957SAndroid Build Coastguard Worker }
545*9e564957SAndroid Build Coastguard Worker
iconv_bmap(const char * path,size_t blocksize,uint64_t * idx)546*9e564957SAndroid Build Coastguard Worker static int iconv_bmap(const char *path, size_t blocksize, uint64_t *idx)
547*9e564957SAndroid Build Coastguard Worker {
548*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
549*9e564957SAndroid Build Coastguard Worker char *newpath;
550*9e564957SAndroid Build Coastguard Worker int err = iconv_convpath(ic, path, &newpath, 0);
551*9e564957SAndroid Build Coastguard Worker if (!err) {
552*9e564957SAndroid Build Coastguard Worker err = fuse_fs_bmap(ic->next, newpath, blocksize, idx);
553*9e564957SAndroid Build Coastguard Worker free(newpath);
554*9e564957SAndroid Build Coastguard Worker }
555*9e564957SAndroid Build Coastguard Worker return err;
556*9e564957SAndroid Build Coastguard Worker }
557*9e564957SAndroid Build Coastguard Worker
iconv_lseek(const char * path,off_t off,int whence,struct fuse_file_info * fi)558*9e564957SAndroid Build Coastguard Worker static off_t iconv_lseek(const char *path, off_t off, int whence,
559*9e564957SAndroid Build Coastguard Worker struct fuse_file_info *fi)
560*9e564957SAndroid Build Coastguard Worker {
561*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
562*9e564957SAndroid Build Coastguard Worker char *newpath;
563*9e564957SAndroid Build Coastguard Worker int res = iconv_convpath(ic, path, &newpath, 0);
564*9e564957SAndroid Build Coastguard Worker if (!res) {
565*9e564957SAndroid Build Coastguard Worker res = fuse_fs_lseek(ic->next, newpath, off, whence, fi);
566*9e564957SAndroid Build Coastguard Worker free(newpath);
567*9e564957SAndroid Build Coastguard Worker }
568*9e564957SAndroid Build Coastguard Worker return res;
569*9e564957SAndroid Build Coastguard Worker }
570*9e564957SAndroid Build Coastguard Worker
iconv_init(struct fuse_conn_info * conn,struct fuse_config * cfg)571*9e564957SAndroid Build Coastguard Worker static void *iconv_init(struct fuse_conn_info *conn,
572*9e564957SAndroid Build Coastguard Worker struct fuse_config *cfg)
573*9e564957SAndroid Build Coastguard Worker {
574*9e564957SAndroid Build Coastguard Worker struct iconv *ic = iconv_get();
575*9e564957SAndroid Build Coastguard Worker fuse_fs_init(ic->next, conn, cfg);
576*9e564957SAndroid Build Coastguard Worker /* Don't touch cfg->nullpath_ok, we can work with
577*9e564957SAndroid Build Coastguard Worker either */
578*9e564957SAndroid Build Coastguard Worker return ic;
579*9e564957SAndroid Build Coastguard Worker }
580*9e564957SAndroid Build Coastguard Worker
iconv_destroy(void * data)581*9e564957SAndroid Build Coastguard Worker static void iconv_destroy(void *data)
582*9e564957SAndroid Build Coastguard Worker {
583*9e564957SAndroid Build Coastguard Worker struct iconv *ic = data;
584*9e564957SAndroid Build Coastguard Worker fuse_fs_destroy(ic->next);
585*9e564957SAndroid Build Coastguard Worker iconv_close(ic->tofs);
586*9e564957SAndroid Build Coastguard Worker iconv_close(ic->fromfs);
587*9e564957SAndroid Build Coastguard Worker pthread_mutex_destroy(&ic->lock);
588*9e564957SAndroid Build Coastguard Worker free(ic->from_code);
589*9e564957SAndroid Build Coastguard Worker free(ic->to_code);
590*9e564957SAndroid Build Coastguard Worker free(ic);
591*9e564957SAndroid Build Coastguard Worker }
592*9e564957SAndroid Build Coastguard Worker
593*9e564957SAndroid Build Coastguard Worker static const struct fuse_operations iconv_oper = {
594*9e564957SAndroid Build Coastguard Worker .destroy = iconv_destroy,
595*9e564957SAndroid Build Coastguard Worker .init = iconv_init,
596*9e564957SAndroid Build Coastguard Worker .getattr = iconv_getattr,
597*9e564957SAndroid Build Coastguard Worker .access = iconv_access,
598*9e564957SAndroid Build Coastguard Worker .readlink = iconv_readlink,
599*9e564957SAndroid Build Coastguard Worker .opendir = iconv_opendir,
600*9e564957SAndroid Build Coastguard Worker .readdir = iconv_readdir,
601*9e564957SAndroid Build Coastguard Worker .releasedir = iconv_releasedir,
602*9e564957SAndroid Build Coastguard Worker .mknod = iconv_mknod,
603*9e564957SAndroid Build Coastguard Worker .mkdir = iconv_mkdir,
604*9e564957SAndroid Build Coastguard Worker .symlink = iconv_symlink,
605*9e564957SAndroid Build Coastguard Worker .unlink = iconv_unlink,
606*9e564957SAndroid Build Coastguard Worker .rmdir = iconv_rmdir,
607*9e564957SAndroid Build Coastguard Worker .rename = iconv_rename,
608*9e564957SAndroid Build Coastguard Worker .link = iconv_link,
609*9e564957SAndroid Build Coastguard Worker .chmod = iconv_chmod,
610*9e564957SAndroid Build Coastguard Worker .chown = iconv_chown,
611*9e564957SAndroid Build Coastguard Worker .truncate = iconv_truncate,
612*9e564957SAndroid Build Coastguard Worker .utimens = iconv_utimens,
613*9e564957SAndroid Build Coastguard Worker .create = iconv_create,
614*9e564957SAndroid Build Coastguard Worker .open = iconv_open_file,
615*9e564957SAndroid Build Coastguard Worker .read_buf = iconv_read_buf,
616*9e564957SAndroid Build Coastguard Worker .write_buf = iconv_write_buf,
617*9e564957SAndroid Build Coastguard Worker .statfs = iconv_statfs,
618*9e564957SAndroid Build Coastguard Worker .flush = iconv_flush,
619*9e564957SAndroid Build Coastguard Worker .release = iconv_release,
620*9e564957SAndroid Build Coastguard Worker .fsync = iconv_fsync,
621*9e564957SAndroid Build Coastguard Worker .fsyncdir = iconv_fsyncdir,
622*9e564957SAndroid Build Coastguard Worker .setxattr = iconv_setxattr,
623*9e564957SAndroid Build Coastguard Worker .getxattr = iconv_getxattr,
624*9e564957SAndroid Build Coastguard Worker .listxattr = iconv_listxattr,
625*9e564957SAndroid Build Coastguard Worker .removexattr = iconv_removexattr,
626*9e564957SAndroid Build Coastguard Worker .lock = iconv_lock,
627*9e564957SAndroid Build Coastguard Worker .flock = iconv_flock,
628*9e564957SAndroid Build Coastguard Worker .bmap = iconv_bmap,
629*9e564957SAndroid Build Coastguard Worker .lseek = iconv_lseek,
630*9e564957SAndroid Build Coastguard Worker };
631*9e564957SAndroid Build Coastguard Worker
632*9e564957SAndroid Build Coastguard Worker static const struct fuse_opt iconv_opts[] = {
633*9e564957SAndroid Build Coastguard Worker FUSE_OPT_KEY("-h", 0),
634*9e564957SAndroid Build Coastguard Worker FUSE_OPT_KEY("--help", 0),
635*9e564957SAndroid Build Coastguard Worker { "from_code=%s", offsetof(struct iconv, from_code), 0 },
636*9e564957SAndroid Build Coastguard Worker { "to_code=%s", offsetof(struct iconv, to_code), 1 },
637*9e564957SAndroid Build Coastguard Worker FUSE_OPT_END
638*9e564957SAndroid Build Coastguard Worker };
639*9e564957SAndroid Build Coastguard Worker
iconv_help(void)640*9e564957SAndroid Build Coastguard Worker static void iconv_help(void)
641*9e564957SAndroid Build Coastguard Worker {
642*9e564957SAndroid Build Coastguard Worker char *charmap;
643*9e564957SAndroid Build Coastguard Worker const char *old = setlocale(LC_CTYPE, "");
644*9e564957SAndroid Build Coastguard Worker
645*9e564957SAndroid Build Coastguard Worker charmap = strdup(nl_langinfo(CODESET));
646*9e564957SAndroid Build Coastguard Worker if (old)
647*9e564957SAndroid Build Coastguard Worker setlocale(LC_CTYPE, old);
648*9e564957SAndroid Build Coastguard Worker else
649*9e564957SAndroid Build Coastguard Worker perror("setlocale");
650*9e564957SAndroid Build Coastguard Worker
651*9e564957SAndroid Build Coastguard Worker printf(
652*9e564957SAndroid Build Coastguard Worker " -o from_code=CHARSET original encoding of file names (default: UTF-8)\n"
653*9e564957SAndroid Build Coastguard Worker " -o to_code=CHARSET new encoding of the file names (default: %s)\n",
654*9e564957SAndroid Build Coastguard Worker charmap);
655*9e564957SAndroid Build Coastguard Worker free(charmap);
656*9e564957SAndroid Build Coastguard Worker }
657*9e564957SAndroid Build Coastguard Worker
iconv_opt_proc(void * data,const char * arg,int key,struct fuse_args * outargs)658*9e564957SAndroid Build Coastguard Worker static int iconv_opt_proc(void *data, const char *arg, int key,
659*9e564957SAndroid Build Coastguard Worker struct fuse_args *outargs)
660*9e564957SAndroid Build Coastguard Worker {
661*9e564957SAndroid Build Coastguard Worker (void) data; (void) arg; (void) outargs;
662*9e564957SAndroid Build Coastguard Worker
663*9e564957SAndroid Build Coastguard Worker if (!key) {
664*9e564957SAndroid Build Coastguard Worker iconv_help();
665*9e564957SAndroid Build Coastguard Worker return -1;
666*9e564957SAndroid Build Coastguard Worker }
667*9e564957SAndroid Build Coastguard Worker
668*9e564957SAndroid Build Coastguard Worker return 1;
669*9e564957SAndroid Build Coastguard Worker }
670*9e564957SAndroid Build Coastguard Worker
iconv_new(struct fuse_args * args,struct fuse_fs * next[])671*9e564957SAndroid Build Coastguard Worker static struct fuse_fs *iconv_new(struct fuse_args *args,
672*9e564957SAndroid Build Coastguard Worker struct fuse_fs *next[])
673*9e564957SAndroid Build Coastguard Worker {
674*9e564957SAndroid Build Coastguard Worker struct fuse_fs *fs;
675*9e564957SAndroid Build Coastguard Worker struct iconv *ic;
676*9e564957SAndroid Build Coastguard Worker const char *old = NULL;
677*9e564957SAndroid Build Coastguard Worker const char *from;
678*9e564957SAndroid Build Coastguard Worker const char *to;
679*9e564957SAndroid Build Coastguard Worker
680*9e564957SAndroid Build Coastguard Worker ic = calloc(1, sizeof(struct iconv));
681*9e564957SAndroid Build Coastguard Worker if (ic == NULL) {
682*9e564957SAndroid Build Coastguard Worker fuse_log(FUSE_LOG_ERR, "fuse-iconv: memory allocation failed\n");
683*9e564957SAndroid Build Coastguard Worker return NULL;
684*9e564957SAndroid Build Coastguard Worker }
685*9e564957SAndroid Build Coastguard Worker
686*9e564957SAndroid Build Coastguard Worker if (fuse_opt_parse(args, ic, iconv_opts, iconv_opt_proc) == -1)
687*9e564957SAndroid Build Coastguard Worker goto out_free;
688*9e564957SAndroid Build Coastguard Worker
689*9e564957SAndroid Build Coastguard Worker if (!next[0] || next[1]) {
690*9e564957SAndroid Build Coastguard Worker fuse_log(FUSE_LOG_ERR, "fuse-iconv: exactly one next filesystem required\n");
691*9e564957SAndroid Build Coastguard Worker goto out_free;
692*9e564957SAndroid Build Coastguard Worker }
693*9e564957SAndroid Build Coastguard Worker
694*9e564957SAndroid Build Coastguard Worker from = ic->from_code ? ic->from_code : "UTF-8";
695*9e564957SAndroid Build Coastguard Worker to = ic->to_code ? ic->to_code : "";
696*9e564957SAndroid Build Coastguard Worker /* FIXME: detect charset equivalence? */
697*9e564957SAndroid Build Coastguard Worker if (!to[0])
698*9e564957SAndroid Build Coastguard Worker old = setlocale(LC_CTYPE, "");
699*9e564957SAndroid Build Coastguard Worker ic->tofs = iconv_open(from, to);
700*9e564957SAndroid Build Coastguard Worker if (ic->tofs == (iconv_t) -1) {
701*9e564957SAndroid Build Coastguard Worker fuse_log(FUSE_LOG_ERR, "fuse-iconv: cannot convert from %s to %s\n",
702*9e564957SAndroid Build Coastguard Worker to, from);
703*9e564957SAndroid Build Coastguard Worker goto out_free;
704*9e564957SAndroid Build Coastguard Worker }
705*9e564957SAndroid Build Coastguard Worker ic->fromfs = iconv_open(to, from);
706*9e564957SAndroid Build Coastguard Worker if (ic->tofs == (iconv_t) -1) {
707*9e564957SAndroid Build Coastguard Worker fuse_log(FUSE_LOG_ERR, "fuse-iconv: cannot convert from %s to %s\n",
708*9e564957SAndroid Build Coastguard Worker from, to);
709*9e564957SAndroid Build Coastguard Worker goto out_iconv_close_to;
710*9e564957SAndroid Build Coastguard Worker }
711*9e564957SAndroid Build Coastguard Worker if (old) {
712*9e564957SAndroid Build Coastguard Worker setlocale(LC_CTYPE, old);
713*9e564957SAndroid Build Coastguard Worker old = NULL;
714*9e564957SAndroid Build Coastguard Worker }
715*9e564957SAndroid Build Coastguard Worker
716*9e564957SAndroid Build Coastguard Worker ic->next = next[0];
717*9e564957SAndroid Build Coastguard Worker fs = fuse_fs_new(&iconv_oper, sizeof(iconv_oper), ic);
718*9e564957SAndroid Build Coastguard Worker if (!fs)
719*9e564957SAndroid Build Coastguard Worker goto out_iconv_close_from;
720*9e564957SAndroid Build Coastguard Worker
721*9e564957SAndroid Build Coastguard Worker return fs;
722*9e564957SAndroid Build Coastguard Worker
723*9e564957SAndroid Build Coastguard Worker out_iconv_close_from:
724*9e564957SAndroid Build Coastguard Worker iconv_close(ic->fromfs);
725*9e564957SAndroid Build Coastguard Worker out_iconv_close_to:
726*9e564957SAndroid Build Coastguard Worker iconv_close(ic->tofs);
727*9e564957SAndroid Build Coastguard Worker out_free:
728*9e564957SAndroid Build Coastguard Worker free(ic->from_code);
729*9e564957SAndroid Build Coastguard Worker free(ic->to_code);
730*9e564957SAndroid Build Coastguard Worker free(ic);
731*9e564957SAndroid Build Coastguard Worker if (old) {
732*9e564957SAndroid Build Coastguard Worker setlocale(LC_CTYPE, old);
733*9e564957SAndroid Build Coastguard Worker }
734*9e564957SAndroid Build Coastguard Worker return NULL;
735*9e564957SAndroid Build Coastguard Worker }
736*9e564957SAndroid Build Coastguard Worker
737*9e564957SAndroid Build Coastguard Worker FUSE_REGISTER_MODULE(iconv, iconv_new);
738