我从 fanotify 接收文件系统事件。有时我想获得正在访问的文件的绝对路径。
通常,这不是问题 -fanotify_event_metadata
包含一个文件描述符fd
,所以我可以调用readlink
并/proc/self/fd/<fd>
获取我的路径。
但是,如果路径超出,PATH_MAX
readlink
则无法再使用 - 它会失败并显示ENAMETOOLONG
. 我想知道在这种情况下是否有办法获取文件路径。
显然,我可以fstat
从 fanotify 获得的描述符并遍历整个文件系统,寻找具有相同设备 ID 和 inode 编号的文件。但是这种方法在性能方面对我来说是不可行的(即使我优化它以忽略比 更短的路径PATH_MAX
)。
我尝试通过重新打开并调用来获取fd
父O_PATH
目录openat(fd, "..", ...)
。显然,这失败了,因为fd
没有引用目录。我还尝试在readlink
调用失败后检查缓冲区的内容(希望它包含部分路径)。那也没有用。
到目前为止,我已经设法在打开它们的进程的工作目录中获取文件的长路径(fanotify 事件包含pid
一个目标进程,因此我可以/proc/<pid>/cwd
从那里读取并获取到根目录的路径)。但这是部分解决方案。
有没有办法在不遍历整个文件系统的情况下从文件描述符中获取绝对路径?最好是与内核 2.6.32/glibc 2.11 一起工作的那个。
更新:对于好奇。我已经弄清楚为什么readlink("/proc/self/fd/<fd>", ...
使用足够大的缓冲区来存储整个路径的调用不起作用。
查看do_proc_readlink的实现。请注意,它不buffer
直接使用提供。相反,它分配一个页面并在调用d_path时将其用作临时缓冲区。换句话说,不管有多大buffer
,d_path
总是会被限制在一个页面的大小。在 amd64 上是 4096 字节。一样PATH_MAX
!当它用完提到的页面时,它-ENAMETOOLONG
本身由prepend返回。