Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow handling broken directory offsets #135

Merged
merged 1 commit into from
Aug 8, 2024
Merged

Allow handling broken directory offsets #135

merged 1 commit into from
Aug 8, 2024

Conversation

vasi
Copy link
Owner

@vasi vasi commented Aug 8, 2024

FUSE-T is an implementation of FUSE for macOS, which is becoming popular. But squashfuse doesn't work with FUSE-T, erroring when directories are listed. This is due to FUSE-T supplying improper offset values to the FUSE readdir ops.

Now, squashfuse can be built with --enable-broken-directory-offsets to fix this behavior.

FUSE readdir ops (both high-level and low-level) return lists of directory entries. Each returned entry has an off field, whose value is arbitrary, entirely up to the filesystem. Subsequent calls to readdir can supply one of these offsets to continue reading from the middle of a directory.

In squashfuse, we return as off an offset into the squashfs internal directory entries. This lets us quickly jump to the right entry using the squashfs directory index, without reading all intermediate entries.

However, FUSE-T does NOT supply a previously-returned offset to readdir. Instead, it uses the size of the buffer that squashfuse returned from readdir. This is entirely outside of the FUSE spec! When FUSE-T does this, squashfuse can't find the supplied offset, and errors.

The fix is to simply not attempt to jump to the correct entry. When squashfuse is built with broken-directory-offsets enabled, we just read every entry from the start of the directory, until our buffer size reaches the provided offset. This is inefficient, but probably ok for reasonable directory sizes.

Unfortunately, we need the user to provide a configure argument to trigger this fix. FUSE-T attempts to exactly mirror the FUSE headers and API, so there doesn't seem to be a way to detect this behavior. Even at run-time, FUSE-T could provide a wrong offset that happens to be a valid value, so we can't just look for seek failures.

FUSE-T is an implementation of FUSE for macOS, which is becoming popular. But squashfuse doesn't work with FUSE-T, erroring when directories are listed. This is due to FUSE-T supplying improper `offset` values to the FUSE readdir ops.

Now, squashfuse can be built with `--enable-broken-directory-offsets` to fix this behavior.

FUSE readdir ops (both high-level and low-level) return lists of directory entries. Each returned entry has an `off` field, whose value is arbitrary, entirely up to the filesystem. Subsequent calls to readdir can supply one of these offsets to continue reading from the middle of a directory.

In squashfuse, we return as `off` an offset into the squashfs internal directory entries. This lets us quickly jump to the right entry using the squashfs directory index, without reading all intermediate entries.

However, FUSE-T does NOT supply a previously-returned offset to readdir.
Instead, it uses the size of the buffer that squashfuse returned
from readdir. This is entirely outside of the FUSE spec! When FUSE-T does this, squashfuse can't find the supplied offset, and errors.

The fix is to simply not attempt to jump to the correct entry. When squashfuse is built with broken-directory-offsets enabled, we just read every entry from the start of the directory, until our buffer size reaches the provided offset. This is inefficient, but probably ok for reasonable directory sizes.

Unfortunately, we need the user to provide a `configure` argument to trigger this fix. FUSE-T attempts to exactly mirror the FUSE headers and API, so there doesn't seem to be a way to detect this behavior. Even at run-time, FUSE-T could provide a wrong offset that happens to be a valid value, so we can't just look for seek failures.
@vasi
Copy link
Owner Author

vasi commented Aug 8, 2024

Filed a bug against FUSE-T: macos-fuse-t/fuse-t#63

@vasi vasi merged commit e6ecfb0 into master Aug 8, 2024
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant