#include "fileio.h"
#include "filesystems.h"
#include "fs-util.h"
+#include "missing_fcntl.h"
#include "missing_fs.h"
#include "missing_mount.h"
#include "missing_stat.h"
size_t n = ORIGINAL_MAX_HANDLE_SZ;
- assert((flags & ~(AT_SYMLINK_FOLLOW|AT_EMPTY_PATH)) == 0);
+ assert(fd >= 0 || fd == AT_FDCWD);
+ assert((flags & ~(AT_SYMLINK_FOLLOW|AT_EMPTY_PATH|AT_HANDLE_FID)) == 0);
/* We need to invoke name_to_handle_at() in a loop, given that it might return EOVERFLOW when the specified
* buffer is too small. Note that in contrast to what the docs might suggest, MAX_HANDLE_SZ is only good as a
}
}
+int name_to_handle_at_try_fid(
+ int fd,
+ const char *path,
+ struct file_handle **ret_handle,
+ int *ret_mnt_id,
+ int flags) {
+
+ int r;
+
+ assert(fd >= 0 || fd == AT_FDCWD);
+
+ /* First issues name_to_handle_at() with AT_HANDLE_FID. If this fails and this is not a fatal error
+ * we'll try without the flag, in order to support older kernels that didn't have AT_HANDLE_FID
+ * (i.e. older than Linux 6.5). */
+
+ r = name_to_handle_at_loop(fd, path, ret_handle, ret_mnt_id, flags | AT_HANDLE_FID);
+ if (r >= 0)
+ return r;
+ if (is_name_to_handle_at_fatal_error(r))
+ return r;
+
+ return name_to_handle_at_loop(fd, path, ret_handle, ret_mnt_id, flags & ~AT_HANDLE_FID);
+}
+
static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *ret_mnt_id) {
char path[STRLEN("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)];
_cleanup_free_ char *fdinfo = NULL;
bool is_name_to_handle_at_fatal_error(int err);
int name_to_handle_at_loop(int fd, const char *path, struct file_handle **ret_handle, int *ret_mnt_id, int flags);
+int name_to_handle_at_try_fid(int fd, const char *path, struct file_handle **ret_handle, int *ret_mnt_id, int flags);
bool file_handle_equal(const struct file_handle *a, const struct file_handle *b);