-
Notifications
You must be signed in to change notification settings - Fork 18.8k
Description
I would like to add name_to_handle_at and open_by_handle_at to x/sys/unix for Linux, but I am not sure how to structure the functions and types.
Their canonical definitions are
int name_to_handle_at(int dirfd, const char *pathname, struct file_handle *handle, int *mount_id, int flags);
int open_by_handle_at(int mount_fd, struct file_handle *handle, int flags);
struct file_handle {
unsigned int handle_bytes; /* Size of f_handle [in, out] */
int handle_type; /* Handle type [out] */
unsigned char f_handle[0]; /* File identifier (sized by caller) [out] */
};
My issue is with the open-ended nature of file_handle. The name_to_handle_at syscall expects the user to allocate a file_handle of sufficient size (usually in a loop to determine the correct size) and to put its size in handle_bytes. And while the value of f_handle is opaque, the user may want to access it, for example to transmit it over the network.
I can imagine two possible ways of designing the API, and I am hoping for a third one.
The first option is to stick 1:1 to the C definitions. This would require use of unsafe.Pointer on the caller's side to convert the backing array into the appropriate type, as well as to access the value of f_handle. And due to #14440, the existence of the f_handle field is obscured. Furthermore, I am not sure how this interacts with the GC. If we back a 16 byte struct with an N bytes byte slice, can we be sure GC will never collect part of the memory?
The second option is to split the file_handle argument in two, one for the part of the struct that Go actually generates, and a byte slice for the f_handle, giving us the following:
func NameToHandleAt(..., handle *FileHandle, fHandle []byte, ...)
This, however, begs the question: who's responsibility is it to ensure that handle.Bytes and len(fHandle) match, and what do we do if they don't?
Is there a third option I'm missing?