+ p += strspn(p, WHITESPACE);
+ p[strcspn(p, WHITESPACE)] = 0;
+
+ return safe_atoi(p, mnt_id);
+}
+
+int fd_is_mount_point(int fd) {
+ union file_handle_union h = FILE_HANDLE_INIT, h_parent = FILE_HANDLE_INIT;
+ int mount_id = -1, mount_id_parent = -1;
+ bool nosupp = false, check_st_dev = true;
+ struct stat a, b;
+ int r;
+
+ assert(fd >= 0);
+
+ /* First we will try the name_to_handle_at() syscall, which
+ * tells us the mount id and an opaque file "handle". It is
+ * not supported everywhere though (kernel compile-time
+ * option, not all file systems are hooked up). If it works
+ * the mount id is usually good enough to tell us whether
+ * something is a mount point.
+ *
+ * If that didn't work we will try to read the mount id from
+ * /proc/self/fdinfo/<fd>. This is almost as good as
+ * name_to_handle_at(), however, does not return the the
+ * opaque file handle. The opaque file handle is pretty useful
+ * to detect the root directory, which we should always
+ * consider a mount point. Hence we use this only as
+ * fallback. Exporting the mnt_id in fdinfo is a pretty recent
+ * kernel addition.
+ *
+ * As last fallback we do traditional fstat() based st_dev
+ * comparisons. This is how things were traditionally done,
+ * but unionfs breaks breaks this since it exposes file
+ * systems with a variety of st_dev reported. Also, btrfs
+ * subvolumes have different st_dev, even though they aren't
+ * real mounts of their own. */
+