fd-util: Add dir_fd_is_root()
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
#include "missing_fcntl.h"
|
||||
#include "missing_fs.h"
|
||||
#include "missing_syscall.h"
|
||||
#include "mountpoint-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
@@ -864,3 +865,54 @@ int fd_get_diskseq(int fd, uint64_t *ret) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dir_fd_is_root(int dir_fd) {
|
||||
STRUCT_NEW_STATX_DEFINE(st);
|
||||
STRUCT_NEW_STATX_DEFINE(pst);
|
||||
int r;
|
||||
|
||||
assert(dir_fd >= 0);
|
||||
|
||||
r = statx_fallback(dir_fd, ".", 0, STATX_TYPE|STATX_INO|STATX_MNT_ID, &st.sx);
|
||||
if (r == -ENOTDIR)
|
||||
return false;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!FLAGS_SET(st.nsx.stx_mask, STATX_MNT_ID)) {
|
||||
int mntid;
|
||||
|
||||
r = path_get_mnt_id_at(dir_fd, "", &mntid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
assert(mntid >= 0);
|
||||
|
||||
st.nsx.stx_mnt_id = mntid;
|
||||
st.nsx.stx_mask |= STATX_MNT_ID;
|
||||
}
|
||||
|
||||
r = statx_fallback(dir_fd, "..", 0, STATX_TYPE|STATX_INO|STATX_MNT_ID, &pst.sx);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!FLAGS_SET(pst.nsx.stx_mask, STATX_MNT_ID)) {
|
||||
int mntid;
|
||||
|
||||
r = path_get_mnt_id_at(dir_fd, "..", &mntid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
assert(mntid >= 0);
|
||||
|
||||
pst.nsx.stx_mnt_id = mntid;
|
||||
pst.nsx.stx_mask |= STATX_MNT_ID;
|
||||
}
|
||||
|
||||
/* If the parent directory is the same inode, the fd points to the root directory "/". We also check
|
||||
* that the mount ids are the same. Otherwise, a construct like the following could be used to trick
|
||||
* us:
|
||||
*
|
||||
* $ mkdir /tmp/x /tmp/x/y
|
||||
* $ mount --bind /tmp/x /tmp/x/y
|
||||
*/
|
||||
return statx_inode_same(&st.sx, &pst.sx) && statx_mount_same(&st.nsx, &pst.nsx);
|
||||
}
|
||||
|
||||
@@ -100,6 +100,8 @@ int fd_is_opath(int fd);
|
||||
int read_nr_open(void);
|
||||
int fd_get_diskseq(int fd, uint64_t *ret);
|
||||
|
||||
int dir_fd_is_root(int dir_fd);
|
||||
|
||||
/* The maximum length a buffer for a /proc/self/fd/<fd> path needs */
|
||||
#define PROC_FD_PATH_MAX \
|
||||
(STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int))
|
||||
|
||||
Reference in New Issue
Block a user