|
| 1 | +# MacOS Rename Issue |
| 2 | + |
| 3 | +I've create a MemFS with `fuser` and I'm having issue with the rename operation on MacOS (using [email protected]) where the rename request is provided with empty filenames: |
| 4 | + |
| 5 | +```shell |
| 6 | +touch bar |
| 7 | +mv bar zar |
| 8 | +``` |
| 9 | + |
| 10 | +Result in the following Request log: |
| 11 | + |
| 12 | +```txt |
| 13 | +FUSE( 4) ino 0x00..01 RENAME src FilenameDir { dir: Inode(1), name: "" }, dest FilenameDir { dir: Inode(1), name: "" } |
| 14 | +``` |
| 15 | + |
| 16 | +I've added a log that dump the content of `data` before it's decoded into the Rename Request: |
| 17 | + |
| 18 | +```txt |
| 19 | +Parsing opcode FUSE_RENAME, data: AQAAAAAAAAAAAAAAAAAAAGJhcgB6YXIA |
| 20 | +``` |
| 21 | + |
| 22 | +By decoding the data, we get: |
| 23 | + |
| 24 | +```shell |
| 25 | +$ echo AQAAAAAAAAAAAAAAAAAAAGJhcgB6YXIA | base64 --decode | xxd |
| 26 | +00000000: 0100 0000 0000 0000 0000 0000 0000 0000 ................ |
| 27 | +00000010: 6261 7200 7a61 7200 bar.zar. |
| 28 | +``` |
| 29 | + |
| 30 | +So we have the filenames that are provided, that mean the issue is during the parsing of the low-level request from macFuse. |
| 31 | +`fuser` define the Rename request like so: |
| 32 | + |
| 33 | +```rust |
| 34 | +#[derive(Debug)] |
| 35 | +pub struct Rename<'a> { |
| 36 | + header: &'a fuse_in_header, |
| 37 | + arg: &'a fuse_rename_in, |
| 38 | + name: &'a Path, |
| 39 | + newname: &'a Path, |
| 40 | +} |
| 41 | +``` |
| 42 | + |
| 43 | +> [`Rename`](https://github.com/cberner/fuser/blob/424bbcaa30a586a6dc99b5019f5e9b9f7755a31f/src/ll/request.rs#L581-L587) |
| 44 | +
|
| 45 | +```rust |
| 46 | +#[repr(C)] |
| 47 | +#[derive(Debug, FromBytes, FromZeroes)] |
| 48 | +pub struct fuse_rename_in { |
| 49 | + pub newdir: u64, |
| 50 | +} |
| 51 | +``` |
| 52 | + |
| 53 | +> [`fuse_rename_in`](https://github.com/cberner/fuser/blob/v0.14.0/src/ll/fuse_abi.rs#L584-L588) |
| 54 | +
|
| 55 | +Parsing the provided data by MacFuse result in: |
| 56 | + |
| 57 | +```rst |
| 58 | ++---------------------+------------+---------------+------------------------------------+ |
| 59 | +| Rename | |
| 60 | ++=====================+============+===============+====================================+ |
| 61 | +| fuse_rename_in | | |
| 62 | ++---------------------+------------+---------------+------------------------------------+ |
| 63 | +| newdir: u64 | name: Path | newname: Path | _unused_ | |
| 64 | ++---------------------+------------+---------------+------------------------------------+ |
| 65 | +| 0100 0000 0000 0000 | 00 | 00 | 0000 0000 0000 6261 7200 7a61 7200 | |
| 66 | ++---------------------+------------+---------------+------------------------------------+ |
| 67 | +``` |
| 68 | + |
| 69 | +`fuse_rename_in` is defined as the following on MacFuse: |
| 70 | + |
| 71 | +```c |
| 72 | +struct fuse_rename_in { |
| 73 | + __u64 newdir; |
| 74 | +#ifdef __APPLE__ |
| 75 | + __u32 flags; |
| 76 | + __u32 padding; |
| 77 | +#endif |
| 78 | +}; |
| 79 | +``` |
| 80 | + |
| 81 | +> [`fuse_rename_in`](https://github.com/osxfuse/fuse/blob/6f7322893456f6ff9db145f096b9bfc2ba95d627/include/fuse_kernel.h#L446-L452) |
| 82 | +
|
| 83 | +If we map the data received, everything seems to _click into place_: |
| 84 | + |
| 85 | +```rst |
| 86 | ++---------------------+------------+--------------+------------+---------------+ |
| 87 | +| Rename | |
| 88 | ++=====================+============+==============+============+===============+ |
| 89 | +| fuse_rename_in | | |
| 90 | ++---------------------+------------+--------------+------------+---------------+ |
| 91 | +| newdir: u64 | flags: u32 | padding: u32 | name: Path | newname: Path | |
| 92 | ++---------------------+------------+--------------+------------+---------------+ |
| 93 | +| 0100 0000 0000 0000 | 0000 0000 | 0000 0000 | 6261 7200 | 7a61 7200 | |
| 94 | ++---------------------+------------+--------------+------------+---------------+ |
| 95 | +``` |
0 commit comments