Skip to content

Conversation

@bertschingert
Copy link
Contributor

This adds support for {name_to,open_by}_handle_at(2) on Linux.

I have a Rust application that wants to use these syscalls and it would be really nice to use a standard library rather than roll my own wrappers.

I would consider this an RFC at this point because I do have a few open questions about the API:

  1. I don't believe it's valid for user applications to interpret or modify the handle_bytes and handle_type fields, even though they are exposed in the C struct definition. (The handle_bytes field does need to be accessed to size the handle correctly, but that is handled by this library, so user apps need not worry about that.) So this API makes struct FileHandle entirely opaque. If I'm wrong and there is a valid reason for a user app to access those fields, I think getter/setters could be added in the future without breaking the API...
  2. It could be useful to have some kind of BorrowedFileHandle type that contains &[u8] instead of Box<[u8]> -- I don't immediately have a use case for it, so I didn't implement it, but putting it out there in case the idea does seem useful
  3. name_to_handle_at(2) is interesting in that its signature is different depending on the flag AT_HANDLE_MNT_ID_UNIQUE -- the mount_id parameter is either an int *, or u64 *. I thought of two ways to handle this in rust: create a separate name_to_handle_at_unique() function for the u64 variant, or create an Enum so that one function can return both kinds of mount_id. I went with the latter, but I could see an argument for the former being better. Thoughts?

I want to be able to store a filehandle and/or send it over the network, and then use it again when I get it back, so that is the reason for adding public from_raw() and into_raw() methods onto struct FileHandle.

Another question is how to test this -- since open_by_handle_at(2) requires CAP_DAC_READ_SEARCH privilege, programs that use it typically run as root. Is there a precedent for how to write unit/integration tests that require root in Rustix? (I have an external test program I ran with sudo to test this, I can share it if that would be helpful.)

This way, once the user gets it, the filehandle slice is only as large
as it needs to be. Then if the user copies it, excess unused bytes are
not copied.

/// This maximum is more of a "guideline"; the man page for name_to_handle_at(2) indicates it could
/// increase in the future.
const MAX_HANDLE_SIZE: usize = 128;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this correspond to MAX_HANDLE_SZ in libc? If so, could you add a comment about this?

@sunfishcode
Copy link
Member

Currently, tests requiring non-default Linux capabilities are just #[ignore]ed, unfortunately. If anyone has any ideas on better ways to do that, they'd be appreciated.

I myself don't know anything about open_by_handle_at and name_to_handle_at. From what you've described here, making handle_bytes and handle_type entirely opaque makes sense. Even if there is some obscure way to use them that's somehow valid, completeness over theoretically possible functionality isn't a requirement for rustix.

Concerning 2, I agree an API to avoid the Box is theoretically nice, but we don't need to block on that if we don't have an immediate need for it.

Concerning 3, rustix tries to guess whether use cases using these functions would have a need to decide which variant to use dynamically. If so, then it makes more sense to do an enum. But if not, then separate functions like name_to_handle_at_unique make sense. An example of this is how mmap_anonymous is split out of mmap; users tend to know whether they're doing an anonymous mmap or not in the code, so it doesn't need to be dynamic.

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.

2 participants