yarf/
lib.rs

1/*
2 * A Rust-friendly API for yarf-sys.
3 * It supports only libfuse 2.6.x+
4 *
5 */
6extern crate libc;
7extern crate yarf_sys;
8
9use libc::{off_t, stat};
10use std::ffi::{CStr, CString};
11use std::mem;
12use std::os::raw::{c_char, c_int, c_void};
13use std::slice;
14
15pub type FuseConnectionInfo = ::yarf_sys::fuse_conn_info;
16pub type FuseDirHandler = ::yarf_sys::fuse_dirh_t;
17pub type FuseDirFil = ::yarf_sys::fuse_dirfil_t;
18pub type FuseFileInfo = ::yarf_sys::fuse_file_info;
19pub type FuseOperations = ::yarf_sys::fuse_operations;
20
21#[doc = "A filesystem on FUSE"]
22pub trait FileSystem {
23    #[doc = " Get file attributes."]
24    fn getattr(&self, _path: String, _stbuf: Option<&mut stat>) -> c_int {
25        -libc::ENOSYS
26    }
27
28    #[doc = " Read the target of a symbolic link"]
29    fn readlink(&self, _path: String, _buf: &mut [u8]) -> ::std::os::raw::c_int {
30        -libc::ENOSYS
31    }
32
33    fn getdir(&self, _path: String, _arg2: FuseDirHandler, _arg3: FuseDirFil) -> c_int {
34        -libc::ENOSYS
35    }
36
37    #[doc = " Create a file node"]
38    fn mknod(&self, _path: String, _mode: ::libc::mode_t, _dev: ::libc::dev_t) -> c_int {
39        -libc::ENOSYS
40    }
41
42    #[doc = " Create a directory"]
43    fn mkdir(&self, _path: String, _mode: ::libc::mode_t) -> c_int {
44        -libc::ENOSYS
45    }
46
47    #[doc = " Remove a file"]
48    fn unlink(&self, _path: String) -> c_int {
49        -libc::ENOSYS
50    }
51
52    #[doc = " Remove a directory"]
53    fn rmdir(&self, _path: String) -> c_int {
54        -libc::ENOSYS
55    }
56
57    #[doc = " Create a symbolic link"]
58    fn symlink(&self, _path1: String, _path2: String) -> c_int {
59        -libc::ENOSYS
60    }
61
62    #[doc = " Rename a file"]
63    fn rename(&self, _old: String, _new: String) -> c_int {
64        -libc::ENOSYS
65    }
66
67    #[doc = " Create a hard link to a file"]
68    fn link(&self, _path1: String, _path2: String) -> c_int {
69        -libc::ENOSYS
70    }
71
72    #[doc = " Change the permission bits of a file"]
73    fn chmod(&self, _path: String, _mode: ::libc::mode_t) -> c_int {
74        -libc::ENOSYS
75    }
76
77    #[doc = " Change the owner and group of a file"]
78    fn chown(&self, _path: String, _uid: ::libc::uid_t, _gid: ::libc::gid_t) -> c_int {
79        -libc::ENOSYS
80    }
81
82    #[doc = " Change the size of a file"]
83    fn truncate(&self, _path: String, _offset: ::libc::off_t) -> c_int {
84        -libc::ENOSYS
85    }
86
87    #[doc = " Change the access and/or modification times of a file"]
88    fn utime(&self, _path: String, _utimbuf: Option<&mut ::libc::utimbuf>) -> c_int {
89        -libc::ENOSYS
90    }
91
92    #[doc = " File open operation"]
93    fn open(&self, _path: String, _fi: Option<&mut FuseFileInfo>) -> c_int {
94        0
95    }
96
97    #[doc = " Read data from an open file"]
98    fn read(
99        &self,
100        _path: String,
101        _buf: &mut [u8],
102        _offset: off_t,
103        _fi: Option<&mut FuseFileInfo>,
104    ) -> c_int {
105        -libc::ENOSYS
106    }
107
108    #[doc = " Write data to an open file"]
109    fn write(
110        &self,
111        _path: String,
112        _buf: &[u8],
113        _offset: ::libc::off_t,
114        _fi: Option<&mut FuseFileInfo>,
115    ) -> c_int {
116        -libc::ENOSYS
117    }
118
119    #[doc = " Get file system statistics"]
120    fn statfs(&self, _path: String, _statvfs: Option<&mut ::libc::statvfs>) -> c_int {
121        0
122    }
123
124    #[doc = " Possibly flush cached data"]
125    fn flush(&self, _path: String, _fi: Option<&mut FuseFileInfo>) -> c_int {
126        -libc::ENOSYS
127    }
128
129    #[doc = " Release an open file"]
130    fn release(&self, _path: String, _fi: Option<&mut FuseFileInfo>) -> c_int {
131        0
132    }
133
134    #[doc = " Synchronize file contents"]
135    fn fsync(
136        &self,
137        _path: String,
138        _arg2: ::std::os::raw::c_int,
139        _fi: Option<&mut FuseFileInfo>,
140    ) -> c_int {
141        -libc::ENOSYS
142    }
143
144    fn setxattr(
145        &self,
146        _path: String,
147        _name: String,
148        _value: &[u8],
149        _arg5: c_int,
150        _arg6: u32,
151    ) -> ::std::os::raw::c_int {
152        -libc::ENOSYS
153    }
154
155    fn getxattr(&self, _path: String, _name: String, _value: &[u8], _arg5: u32) -> c_int {
156        -libc::ENOSYS
157    }
158
159    #[doc = " List extended attributes"]
160    fn listxattr(&self, _path: String, _buf: &mut [u8]) -> c_int {
161        -libc::ENOSYS
162    }
163
164    #[doc = " Remove extended attributes"]
165    fn removexattr(&self, _path: String, _name: String) -> c_int {
166        -libc::ENOSYS
167    }
168
169    #[doc = " Open directory"]
170    fn opendir(&self, _path: String, _fi: Option<&mut FuseFileInfo>) -> c_int {
171        0
172    }
173
174    #[doc = " Read directory"]
175    fn readdir(
176        &self,
177        _path: String,
178        _filler: ReadDirFiller,
179        _offset: off_t,
180        _fi: Option<&mut FuseFileInfo>,
181    ) -> c_int {
182        -libc::ENOSYS
183    }
184
185    #[doc = " Release directory"]
186    fn releasedir(&self, _path: String, _fi: Option<&mut FuseFileInfo>) -> c_int {
187        0
188    }
189
190    #[doc = " Synchronize directory contents"]
191    fn fsyncdir(
192        &self,
193        _path: String,
194        _arg2: ::std::os::raw::c_int,
195        _fi: Option<&mut FuseFileInfo>,
196    ) -> c_int {
197        -libc::ENOSYS
198    }
199
200    // NOTE unsupported
201    // #[doc = " Initialize filesystem"]
202    // fn init(&self, _conn: *mut FuseConnectionInfo) -> *mut c_void {
203    //     ptr::null_mut()
204    // }
205    // NOTE unsupported
206    // #[doc = " Clean up filesystem"]
207    // fn destroy(&self, arg1: *mut ::std::os::raw::c_void) {
208    // }
209
210    #[doc = " Check file access permissions"]
211    fn access(&self, _path: String, _mode: ::std::os::raw::c_int) -> c_int {
212        -libc::ENOSYS
213    }
214
215    #[doc = " Create and open a file"]
216    fn create(
217        &self,
218        _path: String,
219        _mode: ::libc::mode_t,
220        _fi: Option<&mut FuseFileInfo>,
221    ) -> c_int {
222        -libc::ENOSYS
223    }
224
225    #[doc = " Change the size of an open file"]
226    fn ftruncate(
227        &self,
228        _path: String,
229        _offset: ::libc::off_t,
230        _fi: Option<&mut FuseFileInfo>,
231    ) -> c_int {
232        -libc::ENOSYS
233    }
234
235    #[doc = " Get attributes from an open file"]
236    fn fgetattr(
237        &self,
238        _path: String,
239        _stbuf: Option<&mut ::libc::stat>,
240        _fi: Option<&mut FuseFileInfo>,
241    ) -> c_int {
242        -libc::ENOSYS
243    }
244
245    #[doc = " Perform POSIX file locking operation"]
246    fn lock(
247        &self,
248        _path: String,
249        _fi: Option<&mut FuseFileInfo>,
250        _cmd: ::std::os::raw::c_int,
251        _arg3: *mut ::libc::flock,
252    ) -> c_int {
253        -libc::ENOSYS
254    }
255
256    #[doc = " Change the access and modification times of a file with"]
257    fn utimens(&self, _path: String, _tv: ::libc::timespec) -> c_int {
258        -libc::ENOSYS
259    }
260
261    #[doc = " Map block index within file to block index within device"]
262    fn bmap(&self, _path: String, _blocksize: usize, _idx: &mut u64) -> c_int {
263        -libc::ENOSYS
264    }
265}
266
267#[doc = "safety fuse_fill_dir"]
268pub struct ReadDirFiller {
269    buf: *mut ::std::os::raw::c_void,
270    raw_filler: ::yarf_sys::fuse_fill_dir_t,
271}
272
273impl ReadDirFiller {
274    pub fn new(
275        buf: *mut ::std::os::raw::c_void,
276        raw_filler: ::yarf_sys::fuse_fill_dir_t,
277    ) -> ReadDirFiller {
278        ReadDirFiller { buf, raw_filler }
279    }
280
281    #[doc = "fill directory info"]
282    pub fn fill(
283        &self,
284        name: &str,
285        stbuf: *const stat,
286        offset: ::libc::off_t,
287    ) -> ::std::os::raw::c_int {
288        if let Some(func) = self.raw_filler {
289            if let Ok(cname) = CString::new(name) {
290                return unsafe { func(self.buf, cname.as_ptr(), stbuf, offset) };
291            }
292        }
293        -libc::EIO
294    }
295}
296
297#[doc = "main() for your FileSystem implementation"]
298pub fn yarf_main(fs: Box<FileSystem>) -> i64 {
299    let ops = FuseOperations {
300        getattr: Some(getattr_proxy),
301        readlink: Some(readlink_proxy),
302        getdir: Some(getdir_proxy),
303        mknod: Some(mknod_proxy),
304        mkdir: Some(mkdir_proxy),
305        unlink: Some(unlink_proxy),
306        rmdir: Some(rmdir_proxy),
307        symlink: Some(symlink_proxy),
308        rename: Some(rename_proxy),
309        link: Some(link_proxy),
310        chmod: Some(chmod_proxy),
311        chown: Some(chown_proxy),
312        truncate: Some(truncate_proxy),
313        utime: Some(utime_proxy),
314        open: Some(open_proxy),
315        read: Some(read_proxy),
316        write: Some(write_proxy),
317        statfs: Some(statfs_proxy),
318        flush: Some(flush_proxy),
319        release: Some(release_proxy),
320        fsync: Some(fsync_proxy),
321        setxattr: Some(setxattr_proxy),
322        getxattr: Some(getxattr_proxy),
323        listxattr: Some(listxattr_proxy),
324        removexattr: Some(removexattr_proxy),
325        opendir: Some(opendir_proxy),
326        readdir: Some(readdir_proxy),
327        releasedir: Some(releasedir_proxy),
328        fsyncdir: Some(fsyncdir_proxy),
329        init: None, // Unsupported because it overwrites private_data used to passing Rust value
330        destroy: None, // Unsupported
331        access: Some(access_proxy),
332        create: Some(create_proxy),
333        ftruncate: Some(ftruncate_proxy),
334        fgetattr: Some(fgetattr_proxy),
335        lock: Some(lock_proxy),
336        utimens: Some(utimens_proxy),
337        bmap: Some(bmap_proxy),
338        reserved00: None,
339        reserved01: None,
340        reserved02: None,
341        reserved03: None,
342        reserved04: None,
343        reserved05: None,
344        reserved06: None,
345        reserved07: None,
346        reserved08: None,
347        reserved09: None,
348        reserved10: None,
349        setvolname: None,
350        exchange: None,
351        getxtimes: None,
352        setbkuptime: None,
353        setchgtime: None,
354        setcrtime: None,
355        chflags: None,
356        setattr_x: None,
357        fsetattr_x: None,
358    };
359
360    // get CLI args
361    let args = std::env::args()
362        .map(|arg| CString::new(arg).unwrap())
363        .collect::<Vec<CString>>();
364    let c_args = args
365        .iter()
366        .map(|arg| arg.as_ptr())
367        .collect::<Vec<*const c_char>>();
368
369    let fstmp = Box::new(fs);
370    let fsptr = Box::into_raw(fstmp) as *mut Box<FileSystem> as *mut c_void;
371    let opsize = mem::size_of::<FuseOperations>();
372
373    // call fuse_main
374    unsafe {
375        yarf_sys::fuse_main_real(
376            c_args.len() as c_int,
377            c_args.as_ptr() as *mut *mut c_char,
378            &ops,
379            opsize,
380            fsptr,
381        )
382    };
383
384    0
385}
386
387//
388// Fuse Callback proxies
389// These handle libfuse callbacks and unsafe processing to provide safe Rust-friendly methods.
390//
391
392extern "C" fn getattr_proxy(path: *const c_char, stbuf: *mut stat) -> c_int {
393    let fs = get_filesystem().unwrap();
394    let rpath = to_rust_str(path);
395
396    // Trust libfuse not to pass invalid pointer
397    let stbuf_ref = unsafe {
398        libc::memset(stbuf as *mut c_void, 0, mem::size_of_val(&stbuf));
399        stbuf.as_mut()
400    };
401
402    fs.getattr(rpath, stbuf_ref)
403}
404
405extern "C" fn readlink_proxy(
406    path: *const ::std::os::raw::c_char,
407    buf: *mut ::std::os::raw::c_char,
408    size: usize,
409) -> ::std::os::raw::c_int {
410    let fs = get_filesystem().unwrap();
411    let rpath = to_rust_str(path);
412    let sbuf = unsafe { slice::from_raw_parts_mut(buf as *mut u8, size) };
413
414    fs.readlink(rpath, sbuf)
415}
416
417extern "C" fn getdir_proxy(
418    path: *const ::std::os::raw::c_char,
419    arg2: ::yarf_sys::fuse_dirh_t,
420    arg3: ::yarf_sys::fuse_dirfil_t,
421) -> ::std::os::raw::c_int {
422    let fs = get_filesystem().unwrap();
423    let rpath = to_rust_str(path);
424
425    fs.getdir(rpath, arg2, arg3)
426}
427
428extern "C" fn mknod_proxy(
429    path: *const ::std::os::raw::c_char,
430    mode: ::libc::mode_t,
431    dev: ::libc::dev_t,
432) -> ::std::os::raw::c_int {
433    let fs = get_filesystem().unwrap();
434    let rpath = to_rust_str(path);
435
436    fs.mknod(rpath, mode, dev)
437}
438
439extern "C" fn mkdir_proxy(
440    path: *const ::std::os::raw::c_char,
441    mode: ::libc::mode_t,
442) -> ::std::os::raw::c_int {
443    let fs = get_filesystem().unwrap();
444    let rpath = to_rust_str(path);
445
446    fs.mkdir(rpath, mode)
447}
448
449extern "C" fn unlink_proxy(path: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int {
450    let fs = get_filesystem().unwrap();
451    let rpath = to_rust_str(path);
452
453    fs.unlink(rpath)
454}
455
456extern "C" fn rmdir_proxy(path: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int {
457    let fs = get_filesystem().unwrap();
458    let rpath = to_rust_str(path);
459
460    fs.rmdir(rpath)
461}
462
463extern "C" fn symlink_proxy(
464    path1: *const ::std::os::raw::c_char,
465    path2: *const ::std::os::raw::c_char,
466) -> ::std::os::raw::c_int {
467    let fs = get_filesystem().unwrap();
468    let rpath1 = to_rust_str(path1);
469    let rpath2 = to_rust_str(path2);
470
471    fs.symlink(rpath1, rpath2)
472}
473
474extern "C" fn rename_proxy(
475    old: *const ::std::os::raw::c_char,
476    new: *const ::std::os::raw::c_char,
477) -> ::std::os::raw::c_int {
478    let fs = get_filesystem().unwrap();
479    let old_str = to_rust_str(old);
480    let new_str = to_rust_str(new);
481
482    fs.rename(old_str, new_str)
483}
484
485extern "C" fn link_proxy(
486    path1: *const ::std::os::raw::c_char,
487    path2: *const ::std::os::raw::c_char,
488) -> ::std::os::raw::c_int {
489    let fs = get_filesystem().unwrap();
490    let rpath1 = to_rust_str(path1);
491    let rpath2 = to_rust_str(path2);
492
493    fs.link(rpath1, rpath2)
494}
495
496extern "C" fn chmod_proxy(
497    path: *const ::std::os::raw::c_char,
498    mode: ::libc::mode_t,
499) -> ::std::os::raw::c_int {
500    let fs = get_filesystem().unwrap();
501    let rpath = to_rust_str(path);
502
503    fs.chmod(rpath, mode)
504}
505
506extern "C" fn chown_proxy(
507    path: *const ::std::os::raw::c_char,
508    uid: ::libc::uid_t,
509    gid: ::libc::gid_t,
510) -> ::std::os::raw::c_int {
511    let fs = get_filesystem().unwrap();
512    let rpath = to_rust_str(path);
513
514    fs.chown(rpath, uid, gid)
515}
516
517extern "C" fn truncate_proxy(
518    path: *const ::std::os::raw::c_char,
519    offset: ::libc::off_t,
520) -> ::std::os::raw::c_int {
521    let fs = get_filesystem().unwrap();
522    let rpath = to_rust_str(path);
523
524    fs.truncate(rpath, offset)
525}
526
527extern "C" fn utime_proxy(
528    path: *const ::std::os::raw::c_char,
529    utimbuf: *mut ::libc::utimbuf,
530) -> ::std::os::raw::c_int {
531    let fs = get_filesystem().unwrap();
532    let rpath = to_rust_str(path);
533    let utimbuf_ref = unsafe { utimbuf.as_mut() };
534
535    fs.utime(rpath, utimbuf_ref)
536}
537
538extern "C" fn open_proxy(path: *const c_char, fi: *mut FuseFileInfo) -> c_int {
539    let fs = get_filesystem().unwrap();
540    let rpath = to_rust_str(path);
541    let fi_ref = unsafe { fi.as_mut() };
542
543    fs.open(rpath, fi_ref)
544}
545
546extern "C" fn read_proxy(
547    path: *const c_char,
548    buf: *mut c_char,
549    size: usize,
550    offset: off_t,
551    fi: *mut FuseFileInfo,
552) -> c_int {
553    let fs = get_filesystem().unwrap();
554    let rpath = to_rust_str(path);
555    let sbuf = unsafe { slice::from_raw_parts_mut(buf as *mut u8, size) };
556    let fi_ref = unsafe { fi.as_mut() };
557
558    fs.read(rpath, sbuf, offset, fi_ref)
559}
560
561extern "C" fn write_proxy(
562    path: *const ::std::os::raw::c_char,
563    buf: *const ::std::os::raw::c_char,
564    size: usize,
565    offset: ::libc::off_t,
566    fi: *mut FuseFileInfo,
567) -> ::std::os::raw::c_int {
568    let fs = get_filesystem().unwrap();
569    let rpath = to_rust_str(path);
570    let sbuf = unsafe { slice::from_raw_parts(buf as *const u8, size) };
571    let fi_ref = unsafe { fi.as_mut() };
572
573    fs.write(rpath, sbuf, offset, fi_ref)
574}
575
576extern "C" fn statfs_proxy(
577    path: *const ::std::os::raw::c_char,
578    statvfs: *mut ::libc::statvfs,
579) -> ::std::os::raw::c_int {
580    let fs = get_filesystem().unwrap();
581    let rpath = to_rust_str(path);
582    let statvfs_ref = unsafe { statvfs.as_mut() };
583
584    fs.statfs(rpath, statvfs_ref)
585}
586
587extern "C" fn flush_proxy(
588    path: *const ::std::os::raw::c_char,
589    fi: *mut FuseFileInfo,
590) -> ::std::os::raw::c_int {
591    let fs = get_filesystem().unwrap();
592    let rpath = to_rust_str(path);
593    let fi_ref = unsafe { fi.as_mut() };
594
595    fs.flush(rpath, fi_ref)
596}
597
598extern "C" fn release_proxy(
599    path: *const ::std::os::raw::c_char,
600    fi: *mut FuseFileInfo,
601) -> ::std::os::raw::c_int {
602    let fs = get_filesystem().unwrap();
603    let rpath = to_rust_str(path);
604    let fi_ref = unsafe { fi.as_mut() };
605
606    fs.release(rpath, fi_ref)
607}
608
609extern "C" fn fsync_proxy(
610    path: *const ::std::os::raw::c_char,
611    arg2: ::std::os::raw::c_int,
612    fi: *mut FuseFileInfo,
613) -> ::std::os::raw::c_int {
614    let fs = get_filesystem().unwrap();
615    let rpath = to_rust_str(path);
616    let fi_ref = unsafe { fi.as_mut() };
617
618    fs.fsync(rpath, arg2, fi_ref)
619}
620
621extern "C" fn setxattr_proxy(
622    path: *const ::std::os::raw::c_char,
623    name: *const ::std::os::raw::c_char,
624    value: *const ::std::os::raw::c_char,
625    size: usize,
626    arg5: ::std::os::raw::c_int,
627    arg6: u32,
628) -> ::std::os::raw::c_int {
629    let fs = get_filesystem().unwrap();
630    let rpath = to_rust_str(path);
631    let rname = to_rust_str(name);
632    let svalue = unsafe { slice::from_raw_parts(value as *const u8, size) };
633
634    fs.setxattr(rpath, rname, svalue, arg5, arg6)
635}
636
637extern "C" fn getxattr_proxy(
638    path: *const ::std::os::raw::c_char,
639    name: *const ::std::os::raw::c_char,
640    value: *mut ::std::os::raw::c_char,
641    size: usize,
642    arg5: u32,
643) -> ::std::os::raw::c_int {
644    let fs = get_filesystem().unwrap();
645    let rpath = to_rust_str(path);
646    let rname = to_rust_str(name);
647    let svalue = unsafe { slice::from_raw_parts(value as *const u8, size) };
648
649    fs.getxattr(rpath, rname, svalue, arg5)
650}
651
652extern "C" fn listxattr_proxy(
653    path: *const ::std::os::raw::c_char,
654    value: *mut ::std::os::raw::c_char,
655    size: usize,
656) -> ::std::os::raw::c_int {
657    let fs = get_filesystem().unwrap();
658    let rpath = to_rust_str(path);
659    let svalue = unsafe { slice::from_raw_parts_mut(value as *mut u8, size) };
660
661    fs.listxattr(rpath, svalue)
662}
663
664extern "C" fn removexattr_proxy(
665    path: *const ::std::os::raw::c_char,
666    name: *const ::std::os::raw::c_char,
667) -> ::std::os::raw::c_int {
668    let fs = get_filesystem().unwrap();
669    let rpath = to_rust_str(path);
670    let rname = to_rust_str(name);
671
672    fs.removexattr(rpath, rname)
673}
674
675extern "C" fn opendir_proxy(
676    path: *const ::std::os::raw::c_char,
677    fi: *mut FuseFileInfo,
678) -> ::std::os::raw::c_int {
679    let fs = get_filesystem().unwrap();
680    let rpath = to_rust_str(path);
681    let fi_ref = unsafe { fi.as_mut() };
682
683    fs.opendir(rpath, fi_ref)
684}
685
686extern "C" fn readdir_proxy(
687    path: *const c_char,
688    buf: *mut c_void,
689    filler: ::yarf_sys::fuse_fill_dir_t,
690    offset: off_t,
691    fi: *mut FuseFileInfo,
692) -> c_int {
693    let fs = get_filesystem().unwrap();
694    let rpath = to_rust_str(path);
695    let rich_filler = ReadDirFiller::new(buf, filler);
696    let fi_ref = unsafe { fi.as_mut() };
697
698    fs.readdir(rpath, rich_filler, offset, fi_ref)
699}
700
701extern "C" fn releasedir_proxy(
702    path: *const ::std::os::raw::c_char,
703    fi: *mut FuseFileInfo,
704) -> ::std::os::raw::c_int {
705    let fs = get_filesystem().unwrap();
706    let rpath = to_rust_str(path);
707    let fi_ref = unsafe { fi.as_mut() };
708
709    fs.releasedir(rpath, fi_ref)
710}
711
712extern "C" fn fsyncdir_proxy(
713    path: *const ::std::os::raw::c_char,
714    arg2: ::std::os::raw::c_int,
715    fi: *mut FuseFileInfo,
716) -> ::std::os::raw::c_int {
717    let fs = get_filesystem().unwrap();
718    let rpath = to_rust_str(path);
719    let fi_ref = unsafe { fi.as_mut() };
720
721    fs.fsyncdir(rpath, arg2, fi_ref)
722}
723
724extern "C" fn access_proxy(
725    path: *const ::std::os::raw::c_char,
726    mode: ::std::os::raw::c_int,
727) -> ::std::os::raw::c_int {
728    let fs = get_filesystem().unwrap();
729    let rpath = to_rust_str(path);
730
731    fs.access(rpath, mode)
732}
733
734extern "C" fn create_proxy(
735    path: *const ::std::os::raw::c_char,
736    mode: ::libc::mode_t,
737    fi: *mut FuseFileInfo,
738) -> ::std::os::raw::c_int {
739    let fs = get_filesystem().unwrap();
740    let rpath = to_rust_str(path);
741    let fi_ref = unsafe { fi.as_mut() };
742
743    fs.create(rpath, mode, fi_ref)
744}
745
746extern "C" fn ftruncate_proxy(
747    path: *const ::std::os::raw::c_char,
748    offset: ::libc::off_t,
749    fi: *mut FuseFileInfo,
750) -> ::std::os::raw::c_int {
751    let fs = get_filesystem().unwrap();
752    let rpath = to_rust_str(path);
753    let fi_ref = unsafe { fi.as_mut() };
754
755    fs.ftruncate(rpath, offset, fi_ref)
756}
757
758extern "C" fn fgetattr_proxy(
759    path: *const ::std::os::raw::c_char,
760    stbuf: *mut ::libc::stat,
761    fi: *mut FuseFileInfo,
762) -> ::std::os::raw::c_int {
763    let fs = get_filesystem().unwrap();
764    let rpath = to_rust_str(path);
765    let fi_ref = unsafe { fi.as_mut() };
766    let stbuf_ref = unsafe { stbuf.as_mut() };
767
768    fs.fgetattr(rpath, stbuf_ref, fi_ref)
769}
770
771extern "C" fn lock_proxy(
772    path: *const ::std::os::raw::c_char,
773    fi: *mut FuseFileInfo,
774    cmd: ::std::os::raw::c_int,
775    arg3: *mut ::libc::flock,
776) -> ::std::os::raw::c_int {
777    let fs = get_filesystem().unwrap();
778    let rpath = to_rust_str(path);
779    let fi_ref = unsafe { fi.as_mut() };
780
781    fs.lock(rpath, fi_ref, cmd, arg3)
782}
783
784extern "C" fn utimens_proxy(
785    path: *const ::std::os::raw::c_char,
786    tv: *const ::libc::timespec,
787) -> ::std::os::raw::c_int {
788    let fs = get_filesystem().unwrap();
789    let rpath = to_rust_str(path);
790    let rtv = unsafe { tv.as_ref().unwrap() };
791
792    fs.utimens(rpath, *rtv)
793}
794
795extern "C" fn bmap_proxy(
796    path: *const ::std::os::raw::c_char,
797    blocksize: usize,
798    idx: *mut u64,
799) -> ::std::os::raw::c_int {
800    let fs = get_filesystem().unwrap();
801    let rpath = to_rust_str(path);
802    let ridx = unsafe { idx.as_mut().unwrap() };
803
804    fs.bmap(rpath, blocksize, ridx)
805}
806
807//
808// Utils
809//
810
811// Convert c_char to String
812fn to_rust_str(cpath: *const c_char) -> String {
813    let path_cstr = unsafe { CStr::from_ptr(cpath) };
814    let path_str = path_cstr.to_str().unwrap();
815
816    return String::from(path_str);
817}
818
819// Get FileSystem trait via fuse_context
820fn get_filesystem() -> Option<Box<FileSystem>> {
821    let ctx = unsafe { yarf_sys::fuse_get_context() };
822    if ctx.is_null() {
823        return None;
824    }
825
826    let fsbox = unsafe { (*ctx).private_data as *mut Box<FileSystem> };
827    if fsbox.is_null() {
828        return None;
829    }
830
831    let actual = unsafe { fsbox.read() };
832    Some(actual)
833}